📄 btsvc.cxx
字号:
continue;
}
break;
}
BthSetSecurityUI (NULL, 0, 0);
PostMessage (ghWndHidden, WM_USER + 2, 0, 0);
delete gThreadPool;
gThreadPool = NULL;
if (WAIT_OBJECT_0 != WaitForSingleObject (hUIThread, BTH_SERVICE_TIMEOUT))
TerminateThread (hUIThread, 0);
CloseHandle (hUIThread);
CloseHandle (hAuthReq);
gfServiceState = SERVICE_STATE_OFF;
return FALSE;
}
// @func PVOID | HLO_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 BTS_Init (DWORD dwData)
{
#if ! defined (SDK_BUILD)
HANDLE hEvent = OpenEvent (EVENT_ALL_ACCESS, FALSE, L"system/events/bluetooth/btsvc/firstboot");
if (hEvent)
CloseHandle (hEvent);
else {
// intentionally link handle - one event per boot. This is only run once.
CreateEvent (NULL, FALSE, FALSE, L"system/events/bluetooth/btsvc/firstboot");
}
#endif
ghServiceExitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (! ghServiceExitEvent)
return FALSE;
ghServiceThread = CreateThread (NULL, 0, BthServiceThread, NULL, 0, NULL);
if (! ghServiceThread) {
CloseHandle (ghServiceExitEvent);
return FALSE;
}
return TRUE;
}
// @func PVOID | HLO_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 BTS_Deinit(DWORD dwData)
{
if (ghServiceExitEvent) {
SetEvent (ghServiceExitEvent);
CloseHandle (ghServiceExitEvent);
ghServiceExitEvent = NULL;
}
if (ghServiceThread) {
if (WAIT_OBJECT_0 != WaitForSingleObject (ghServiceThread, BTH_SERVICE_TIMEOUT))
TerminateThread (ghServiceThread, 0);
CloseHandle (ghServiceThread);
ghServiceThread = NULL;
}
return TRUE;
}
// @func PVOID | HLO_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 BTS_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
return TRUE;
}
// @func BOOL | HLO_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 BTS_Close (DWORD dwData)
{
return TRUE;
}
// @func DWORD | HLO_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 BTS_Write (DWORD dwData, LPCVOID pInBuf, DWORD dwInLen)
{
return -1;
}
// @func DWORD | HLO_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 BTS_Read (DWORD dwData, LPVOID pBuf, DWORD dwLen)
{
return -1;
}
// @func DWORD | HLO_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 BTS_Seek (DWORD dwData, long pos, DWORD type)
{
return (DWORD)-1;
}
// @func void | HLO_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 BTS_PowerUp(void)
{
return;
}
// @func void | HLO_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 BTS_PowerDown(void)
{
return;
}
// @func BOOL | HLO_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 BTS_IOControl(DWORD dwData, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut)
{
switch (dwCode) {
// Control code sent to start a service (not the same as IOCTL_SERVICE_STARTED).
case IOCTL_SERVICE_START: // start a service that is currently in the stopped stage.
if (gfServiceState == SERVICE_STATE_OFF) {
if (ghServiceThread) {
if (WAIT_TIMEOUT == WaitForSingleObject (ghServiceThread, BTH_SERVICE_TIMEOUT))
return FALSE;
CloseHandle (ghServiceThread);
ghServiceThread = NULL;
}
ResetEvent (ghServiceExitEvent);
ghServiceThread = CreateThread (NULL, 0, BthServiceThread, NULL, 0, NULL);
return ghServiceThread != NULL;
}
SetLastError (ERROR_SERVICE_ALREADY_RUNNING);
return FALSE;
// stop a service and for refresh bring it up again.
// REFRESH is required for more complicated servers
// that only read in their registry configuration
// during initilization.
case IOCTL_SERVICE_REFRESH:
case IOCTL_SERVICE_STOP:
if (gfServiceState == SERVICE_STATE_ON) {
if (ghServiceThread) {
SetEvent (ghServiceExitEvent);
if (WAIT_TIMEOUT == WaitForSingleObject (ghServiceThread, BTH_SERVICE_TIMEOUT))
return FALSE;
CloseHandle (ghServiceThread);
ghServiceThread = NULL;
}
if (dwCode == IOCTL_SERVICE_REFRESH) {
ResetEvent (ghServiceExitEvent);
ghServiceThread = CreateThread (NULL, 0, BthServiceThread, NULL, 0, NULL);
return ghServiceThread != NULL;
}
return TRUE;
}
SetLastError (ERROR_SERVICE_NOT_ACTIVE);
return FALSE;
case IOCTL_SERVICE_STATUS:
if (pBufOut && dwLenOut == sizeof(DWORD)) {
*(DWORD *)pBufOut = gfServiceState;
if (pdwActualOut)
*pdwActualOut = sizeof(DWORD);
return TRUE;
}
break;
// IOCTL_SERVICE_CONTROL contains service specific information passed to it by
// a calling application.
case IOCTL_SERVICE_CONTROL:
return TRUE;
// Called once all initialization has completed and the session is ready
// to start running. By convention all services will (or at least should) be
// passed their service handle (what RegisterService() returns). This value
// can be saved in case a service wishes to call DeregisterService on itself.
//
// This is not available in device.exe!
//
case IOCTL_SERVICE_STARTED:
return TRUE;
case IOCTL_SERVICE_REGISTER_SOCKADDR:
// The super services thread or an application will call this IOCTL will
// pBufIn = NULL as a means of querying whether or not the particular service
// will support having a socket bound to it or not. Service will return FALSE
// if it was not designed to take IOCTL_SERVICE_CONNECTION commands, or
// if it is not ready.
//
// This is not available in device.exe!
//
return FALSE;
case IOCTL_SERVICE_DEREGISTER_SOCKADDR:
// When our sockets are being disconnected this message is sent to us.
//
// This is not available in device.exe!
//
return TRUE;
case IOCTL_SERVICE_CONNECTION:
// This IOControl is called when a socket connection for a socked associated
// with the service comes off the wire. The socket accept() returns is the
// value passed. Note that it is the service's responsibilty to close
// the socket, even if the service is not in the active state.
//
// This is not available in device.exe!
//
return FALSE;
// This can be used to programmatically turn on/off debug zones.
case IOCTL_SERVICE_DEBUG:
return TRUE;
// Unsupported SERVICES IOCTLs
// case IOCTL_SERVICE_INSTALL:
// case IOCTL_SERVICE_UNINSTALL:
}
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -