📄 timesvc.cxx
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*--
Module Name: timesvc.cxx
Abstract: service core
--*/
#include <windows.h>
#include <stdio.h>
#include <svsutil.hxx>
#include <service.h>
#include "../inc/timesvc.h"
#if defined (DEBUG) || defined (_DEBUG)
DBGPARAM dpCurSettings =
{
TEXT("TIMESVC"),
{
TEXT("INIT"),
TEXT("SERVER"),
TEXT("CLIENT"),
TEXT("PACKETS"),
TEXT("TRACE"),
TEXT("DST"),
TEXT("<unused>"),
TEXT("<unused>"),
TEXT("<unused>"),
TEXT("<unused>"),
TEXT("<unused>"),
TEXT("<unused>"),
TEXT("<unused>"),
TEXT("<unused>"),
TEXT("Warning"),
TEXT("Error"),
},
0xc001
};
#endif // DEBUG
static DWORD gStateMap[6][6] = {
{SERVICE_STATE_OFF, SERVICE_STATE_UNKNOWN, SERVICE_STATE_STARTING_UP, SERVICE_STATE_SHUTTING_DOWN, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING},
{SERVICE_STATE_UNKNOWN, SERVICE_STATE_ON, SERVICE_STATE_STARTING_UP, SERVICE_STATE_SHUTTING_DOWN, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING},
{SERVICE_STATE_STARTING_UP, SERVICE_STATE_STARTING_UP, SERVICE_STATE_STARTING_UP, SERVICE_STATE_UNKNOWN, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING},
{SERVICE_STATE_SHUTTING_DOWN, SERVICE_STATE_SHUTTING_DOWN, SERVICE_STATE_UNKNOWN, SERVICE_STATE_SHUTTING_DOWN, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING},
{SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNKNOWN, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING},
{SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNLOADING, SERVICE_STATE_UNINITIALIZED}
};
STDAPI_(BOOL) WINAPI DllEntry (HINSTANCE hinstDLL, DWORD Op, LPVOID lpvReserved) {
switch (Op) {
case DLL_PROCESS_ATTACH :
DisableThreadLibraryCalls((HMODULE)hinstDLL);
if (ERROR_SUCCESS != InitializeSNTP (hinstDLL))
return FALSE;
if (ERROR_SUCCESS != InitializeDST (hinstDLL)) {
DestroySNTP ();
return FALSE;
}
break;
case DLL_PROCESS_DETACH :
DestroyDST ();
DestroySNTP ();
break;
}
return TRUE;
}
// @func PVOID | NTP_Init | Service initialization routine
// @parm DWORD | dwData | Info passed to RegisterDevice
// @rdesc Returns a DWORD which will be passed to Open & Deinit or NULL if
// unable to initialize the device.
//
// This is called only once. Do the startup initialization in a thread
// spawned by this function, but DO NOT BLOCK HERE!
//
extern "C" DWORD NTP_Init (DWORD dwData) {
DEBUGMSG(ZONE_TRACE, (L"[TIMESVC] NTP_Init\r\n"));
if (! (dwData & SERVICE_INIT_STOPPED)) {
if (StartSNTP () != ERROR_SUCCESS)
return FALSE;
if (StartDST () != ERROR_SUCCESS) {
StopSNTP ();
return FALSE;
}
}
return TRUE;
}
// @func PVOID | NTP_Deinit | Device deinitialization routine
// @parm DWORD | dwData | value returned from HLO_Init call
// @rdesc Returns TRUE for success, FALSE for failure.
//
// The library WILL BE UNLOADED after this. Block here
// until the state is completely clear and all the
// threads are gone.
//
extern "C" BOOL NTP_Deinit(DWORD dwData) {
DEBUGMSG(ZONE_TRACE, (L"[TIMESVC] NTP_Deinit\r\n"));
StopDST ();
StopSNTP ();
return TRUE;
}
// @func PVOID | NTP_Open | Device open routine
// @parm DWORD | dwData | value returned from HLO_Init call
// @parm DWORD | dwAccess | requested access (combination of GENERIC_READ
// and GENERIC_WRITE)
// @parm DWORD | dwShareMode | requested share mode (combination of
// FILE_SHARE_READ and FILE_SHARE_WRITE)
// @rdesc Returns a DWORD which will be passed to Read, Write, etc or NULL if
// unable to open device.
//
// We don't do anything here, but in a real service this is a place to create
// client process state. HCO_Close will be called with this handle when the process
// exits or terminates, so the clean-up is easy.
//
extern "C" DWORD NTP_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode) {
return TRUE;
}
// @func BOOL | NTP_Close | Device close routine
// @parm DWORD | dwOpenData | value returned from HLO_Open call
// @rdesc Returns TRUE for success, FALSE for failure
//
// Clean-up the client process state here.
//
extern "C" BOOL NTP_Close (DWORD dwData) {
return TRUE;
}
// @func DWORD | NTP_Write | Device write routine
// @parm DWORD | dwOpenData | value returned from HLO_Open call
// @parm LPCVOID | pBuf | buffer containing data
// @parm DWORD | len | maximum length to write [IN BYTES, NOT WORDS!!!]
// @rdesc Returns -1 for error, otherwise the number of bytes written. The
// length returned is guaranteed to be the length requested unless an
// error condition occurs.
//
// This is a vestige of streaming driver interface. We don't use it for services.
//
extern "C" DWORD NTP_Write (DWORD dwData, LPCVOID pInBuf, DWORD dwInLen) {
return -1;
}
// @func DWORD | NTP_Read | Device read routine
// @parm DWORD | dwOpenData | value returned from HLO_Open call
// @parm LPVOID | pBuf | buffer to receive data
// @parm DWORD | len | maximum length to read [IN BYTES, not WORDS!!]
// @rdesc Returns 0 for end of file, -1 for error, otherwise the number of
// bytes read. The length returned is guaranteed to be the length
// requested unless end of file or an error condition occurs.
//
// This is a vestige of streaming driver interface. We don't use it for services.
//
extern "C" DWORD NTP_Read (DWORD dwData, LPVOID pBuf, DWORD dwLen) {
return -1;
}
// @func DWORD | NTP_Seek | Device seek routine
// @parm DWORD | dwOpenData | value returned from HLO_Open call
// @parm long | pos | position to seek to (relative to type)
// @parm DWORD | type | FILE_BEGIN, FILE_CURRENT, or FILE_END
// @rdesc Returns current position relative to start of file, or -1 on error
//
// This is a vestige of streaming driver interface. We don't use it for services.
//
extern "C" DWORD NTP_Seek (DWORD dwData, long pos, DWORD type) {
return (DWORD)-1;
}
// @func void | NTP_PowerUp | Device powerup routine
// @comm Called to restore device from suspend mode.
// You cannot call any routines aside from those in your dll in this call.
//
// This is a vestige of streaming driver interface. We don't use it for services.
//
extern "C" void NTP_PowerUp(void) {
return;
}
// @func void | NTP_PowerDown | Device powerdown routine
// @comm Called to suspend device. You cannot call any routines aside from
// those in your dll in this call.
//
// This is a vestige of streaming driver interface. We don't use it for services.
//
extern "C" void NTP_PowerDown(void) {
return;
}
// @func BOOL | NTP_IOControl | Device IO control routine
// @parm DWORD | dwOpenData | value returned from HLO_Open call
// @parm DWORD | dwCode | io control code to be performed
// @parm PBYTE | pBufIn | input data to the device
// @parm DWORD | dwLenIn | number of bytes being passed in
// @parm PBYTE | pBufOut | output data from the device
// @parm DWORD | dwLenOut |maximum number of bytes to receive from device
// @parm PDWORD | pdwActualOut | actual number of bytes received from device// @rdesc Returns TRUE for success, FALSE for failure
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
//
// This is THE way to expose both manageability of the service and the feature API set.
// Consumer of the API set will marshal input arguments into input buffer (pBufIn).
// This function unmarshals it and executes the API, and then marshals output parameters
// into output buffer (pBufOut).
//
extern "C" BOOL NTP_IOControl(DWORD dwData, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut) {
DEBUGMSG(ZONE_TRACE, (L"[TIMESVC] NTP_IOControl 0x%08x\r\n", dwCode));
int iErr = ERROR_INVALID_PARAMETER;
switch (dwCode) {
case IOCTL_SERVICE_START: // start a service that is currently in the stopped stage.
iErr = StartSNTP ();
if (iErr == ERROR_SUCCESS) {
iErr = StartDST ();
if (iErr != ERROR_SUCCESS)
StopSNTP ();
}
break;
case IOCTL_SERVICE_STOP: // start a service that is currently in the stopped stage.
iErr = StopDST ();
if (iErr == ERROR_SUCCESS)
iErr = StopSNTP ();
break;
case IOCTL_SERVICE_REFRESH:
iErr = RefreshSNTP ();
if (iErr == ERROR_SUCCESS)
iErr = RefreshDST ();
break;
case IOCTL_SERVICE_STATUS:
if (pBufOut && (dwLenOut == sizeof(DWORD))) {
DWORD dwState1 = GetStateSNTP ();
DWORD dwState2 = GetStateDST ();
DWORD dwState = SERVICE_STATE_UNKNOWN;
if (dwState1 == SERVICE_STATE_UNKNOWN)
dwState = dwState2;
else if (dwState2 == SERVICE_STATE_UNKNOWN)
dwState = dwState1;
else if ((dwState1 <= 5) && (dwState2 <= 5))
dwState = gStateMap[dwState1][dwState2];
__try {
*(DWORD *)pBufOut = dwState;
if (pdwActualOut)
*pdwActualOut = sizeof(DWORD);
iErr = ERROR_SUCCESS;
} __except (1) {
iErr = ERROR_INVALID_PARAMETER;
}
} else {
iErr = ERROR_INVALID_PARAMETER;
}
break;
case IOCTL_SERVICE_CONTROL:
{
__try {
int fProcessed = FALSE;
iErr = ServiceControlSNTP (pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut, &fProcessed);
if (fProcessed)
break;
iErr = ServiceControlDST (pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut, &fProcessed);
if (fProcessed)
break;
iErr = ERROR_INVALID_PARAMETER;
} __except (1) {
iErr = ERROR_INVALID_PARAMETER;
}
}
break;
case IOCTL_SERVICE_DEBUG:
#if defined (DEBUG) || defined (_DEBUG)
if ((dwLenIn == sizeof(DWORD)) && pBufIn) {
dpCurSettings.ulZoneMask = (*(DWORD *)pBufIn);
iErr = ERROR_SUCCESS;
} else
iErr = ERROR_INVALID_PARAMETER;
#endif
break;
}
SetLastError(iErr);
return iErr == ERROR_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -