⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btmodem.cxx

📁 这些文件包括蓝牙虚拟串口与打印机程序实例
💻 CXX
📖 第 1 页 / 共 3 页
字号:
		CloseHandle (hModemComPort);

		gfServiceState = SERVICE_STATE_OFF;
		return 0;
    }

    if (! SetCommState(hModemComPort, &dcb)) {
		RETAILMSG(1, (L"Bluetooth modem gateway: Initialization failed: could not configure state of modem port (error %d)" CRLF, GetLastError ()));

		CloseHandle (hModemComPort);

		gfServiceState = SERVICE_STATE_OFF;
		return 0;
    }

	// Create and open Bluetooth device

	HANDLE hBthDevice = CreatePort (port, channel, mtu, fAuthenticate, fEncrypt);
	if (! hBthDevice) {
		CloseHandle (hModemComPort);

		gfServiceState = SERVICE_STATE_OFF;
		return 0;
	}

	HANDLE hBthComPort = CreateFile (szBthPortName,
                GENERIC_READ | GENERIC_WRITE,
                0,    // comm devices must be opened w/exclusive-access
                NULL, // no security attrs
                OPEN_EXISTING, // comm devices must use OPEN_EXISTING
                FILE_ATTRIBUTE_NORMAL,    // overlapped I/O 
                NULL  // hTemplate must be NULL for comm devices  
				);

	if (hBthComPort == INVALID_HANDLE_VALUE) {
		RETAILMSG(1, (L"Bluetooth modem gateway: Initialization failed: could not open Bluetooth device port (error %d)" CRLF, GetLastError ()));
		DeactivateDevice (hBthDevice);
		CloseHandle (hModemComPort);

		gfServiceState = SERVICE_STATE_OFF;
		return 0;
	}

    commTimeouts.ReadTotalTimeoutMultiplier = 1;
    commTimeouts.ReadIntervalTimeout = 50;
    commTimeouts.ReadTotalTimeoutConstant = 50;
    commTimeouts.WriteTotalTimeoutMultiplier = 5;
    commTimeouts.WriteTotalTimeoutConstant = 500;

    if (! SetCommTimeouts (hBthComPort, &commTimeouts)) {
		RETAILMSG(1, (L"Bluetooth modem gateway: Initialization failed: could not configure timeouts on bluetooth port (error %d)" CRLF, GetLastError ()));

		CloseHandle (hBthComPort);
		DeactivateDevice (hBthDevice);
		CloseHandle (hModemComPort);

		gfServiceState = SERVICE_STATE_OFF;
		return 0;
    }

	unsigned long ulSdpRecord = RegisterSDP (hBthComPort);

	if (! ulSdpRecord) {
		RETAILMSG(1, (L"Bluetooth modem gateway: Initialization failed: could not register SDP" CRLF));
		CloseHandle (hBthComPort);
		DeactivateDevice (hBthDevice);
		CloseHandle (hModemComPort);

		gfServiceState = SERVICE_STATE_OFF;
		return 0;
	}

	// Go on listening...

	void *ahA[3];
	void *ahB[3];

	ahA[0] = hBthComPort;
	ahA[1] = hModemComPort;
	ahA[2] = BTH_BLUETOOTH_READER;

	ahB[0] = hModemComPort;
	ahB[1] = hBthComPort;
	ahB[2] = BTH_MODEM_READER;

	HANDLE hThreadA = CreateThread (NULL, 0, ComCopyThread, ahA, 0, NULL);
	HANDLE hThreadB = CreateThread (NULL, 0, ComCopyThread, ahB, 0, NULL);

	if (hThreadA && hThreadB) {
		gfServiceState = SERVICE_STATE_ON;
		BT_ADDR bt;
		if (BthReadLocalAddr (&bt) == ERROR_SUCCESS)
			RETAILMSG(1, (L"Bluetooth modem gateway: Initialization complete. Local address %04x%08x" CRLF, GET_NAP(bt), GET_SAP(bt)));
		else
			RETAILMSG(1, (L"Bluetooth modem gateway: Initialization complete. No bluetooth adapter detected." CRLF));

		WaitForSingleObject (ghServiceExitEvent, INFINITE);
	} else
		RETAILMSG(1, (L"Bluetooth modem gateway: could not create worker threads." CRLF));

	gfServiceState = SERVICE_STATE_SHUTTING_DOWN;

	RETAILMSG(1, (L"Bluetooth modem gateway: closing down." CRLF));
	SetEvent (ghServiceExitEvent);
	CloseHandle (hBthComPort);
	HangUpModem (hModemComPort);
	CloseHandle (hModemComPort);

	DeRegisterSDP (ulSdpRecord);
	DeactivateDevice (hBthDevice);

	if (hThreadA) {
		if (WAIT_TIMEOUT != WaitForSingleObject (hThreadA, BTH_MODEM_TIMEOUT))
			TerminateThread (hThreadA, 0);
		CloseHandle (hThreadA);
	}

	if (hThreadB) {
		if (WAIT_TIMEOUT != WaitForSingleObject (hThreadB, BTH_MODEM_TIMEOUT))
			TerminateThread (hThreadB, 0);
		CloseHandle (hThreadB);
	}

	gfServiceState = SERVICE_STATE_OFF;

	RETAILMSG(1, (L"Bluetooth modem gateway: down." CRLF));

	return 0;
}

//  @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 BTM_Init (DWORD dwData)
{
	ghServiceExitEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
	if (! ghServiceExitEvent)
		return 0;

	ghServiceThread = CreateThread (NULL, 0, ComServiceThread, NULL, 0, NULL);
	if (! ghServiceThread) {
		CloseHandle (ghServiceExitEvent);
		return 0;
	}

    return 1;
}

//  @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 BTM_Deinit(DWORD dwData)
{
	if (ghServiceExitEvent) {
		SetEvent (ghServiceExitEvent);
		CloseHandle (ghServiceExitEvent);
		ghServiceExitEvent = NULL;
	}

	if (ghServiceThread) {
		if (WAIT_OBJECT_0 != WaitForSingleObject (ghServiceThread, BTH_MODEM_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 BTM_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 BTM_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 BTM_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 BTM_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 BTM_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 BTM_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 BTM_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 BTM_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_MODEM_TIMEOUT))
						return FALSE;

					CloseHandle (ghServiceThread);
					ghServiceThread = NULL;
				}

				ResetEvent (ghServiceExitEvent);
				ghServiceThread = CreateThread (NULL, 0, ComServiceThread, 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_MODEM_TIMEOUT))
						return FALSE;

					CloseHandle (ghServiceThread);
					ghServiceThread = NULL;
				}

				if (dwCode == IOCTL_SERVICE_REFRESH) {
					ResetEvent (ghServiceExitEvent);
					ghServiceThread = CreateThread (NULL, 0, ComServiceThread, 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 + -