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

📄 autolaunch.cpp

📁 一本在讲述USB驱动程式的书 及其范例原码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	static int retries = 0;
	if (retries++ > 5)
		{						// can't create tray icon
		TRACE(TSVCNAME _T(" - Shell_NotifyIcon failed - %d\n"), GetLastError());
		DestroyWindow();
		}						// can't create tray icon

	SetTimer(1, 10000, NULL);
	}							// CAutoLaunch::CreateTrayIcon

///////////////////////////////////////////////////////////////////////////////

int CAutoLaunch::OnCreate(LPCREATESTRUCT csp)
	{							// CAutoLaunch::OnCreate
	Log(_T("Starting service"));

	// Register to receive notifications when device drivers enable a GUID_AUTOLAUNCH_NOTIFY
	// interface. Note that we discard the notification handle because we can't unregister
	// it without making Win98 unstable.

	DEV_BROADCAST_DEVICEINTERFACE filter = {0};
	filter.dbcc_size = sizeof(filter);
	filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
	filter.dbcc_classguid = GUID_AUTOLAUNCH_NOTIFY;
	
	HDEVNOTIFY hNotification = RegisterDeviceNotification(m_hWnd, (PVOID) &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
	if (!hNotification)
		{						// can't register for notifications
		TRACE(TSVCNAME _T(" - RegisterDeviceNotification failed - %d\n"), GetLastError());
		return -1;
		}						// can't register for notifications

	// Create a tray icon to give the end user a way to shut this service down

	CreateTrayIcon();

	// Create an initially invisible modeless dialog for asking permission to
	// close the service. If we were just to call MessageBox in the OnMenuClose
	// function, it wouldn't return the first time if we happen to be launched
	// via WinExec from a device driver. The second or third time the user tries to
	// close the service, the call would return to find this object already deleted,
	// and a crash would ensue. This took a while to figure out, I can tell you!

	m_shutdown = new CShutdownDlg(this);

	return 0;
	}							// CAutoLaunch::OnCreate

///////////////////////////////////////////////////////////////////////////////

void CAutoLaunch::OnDestroy()
	{							// CAutoLaunch::OnDestroy
	Log(_T("Shutting service down"));

	NOTIFYICONDATA nid = {sizeof(NOTIFYICONDATA)};
	nid.hWnd = m_hWnd;
	Shell_NotifyIcon(NIM_DELETE, &nid);

	PostQuitMessage(0);
	CWnd::OnDestroy();
	}							// CAutoLaunch::OnDestroy

///////////////////////////////////////////////////////////////////////////////

BOOL CAutoLaunch::OnDeviceChange(UINT evtype, DWORD dwData)
	{							// CAutoLaunch::OnDeviceChange
	HandleDeviceChange(evtype, (_DEV_BROADCAST_HEADER*) dwData);
	return TRUE;
	}							// CAutoLaunch::OnDeviceChange

///////////////////////////////////////////////////////////////////////////////

LRESULT CAutoLaunch::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
	{							// CAutoLaunch::OnNotifyIcon
	if (lParam == WM_RBUTTONDOWN)
		{						// display context menu
		SetForegroundWindow();	// KB Q135788
		CMenu menu;
		menu.LoadMenu(IDR_CONTEXT);

		CMenu* popup = menu.GetSubMenu(0);
		POINT pt;
		UINT flags = TPM_RIGHTBUTTON;
		GetCursorPos(&pt);
		popup->TrackPopupMenu(flags, pt.x, pt.y, this);
		PostMessage(WM_NULL, 0, 0);	// KB Q135788
		}						// display context menu
	return 0;
	}							// CAutoLaunch::OnNotifyIcon

///////////////////////////////////////////////////////////////////////////////

void CAutoLaunch::OnMenuClose()
	{							// CAutoLaunch::OnMenuClose
	m_shutdown->ShowWindow(SW_SHOW);
	}							// CAutoLaunch::OnMenuClose

///////////////////////////////////////////////////////////////////////////////

void CAutoLaunch::OnTimer(UINT id)
	{							// CAutoLaunch::OnTimer
	KillTimer(id);
	CreateTrayIcon();
	}							// CAutoLaunch::OnTimer

///////////////////////////////////////////////////////////////////////////////

void CAutoLaunch::PostNcDestroy()
	{							// CAutoLaunch::PostNcDestroy
	CWnd::PostNcDestroy();
	delete this;
	}							// CAutoLaunch::PostNcDestroy

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

BOOL CAutoLaunchApp::InitInstance()
	{							// CAutoLaunchApp::InitInstance

	// Avoid running two instances of this module

	m_hMutex = CreateMutex(NULL, FALSE, _T("AUTOLAUNCH_MUTEX"));
	if (GetLastError() == ERROR_ALREADY_EXISTS)
		{						// already running
		CloseHandle(m_hMutex);
		return FALSE;
		}						// already running

	// Create an invisible window to receive WM_DEVICECHANGE messages

	CAutoLaunch* dummy = new CAutoLaunch;
	if (!dummy->CreateEx(0, AfxRegisterWndClass(0), _T("Device Driver Service"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL))
		return FALSE;				// give up if can't create window

	m_pMainWnd = dummy;

	return TRUE;
	}							// CAutoLaunchApp::InitInstance

///////////////////////////////////////////////////////////////////////////////

int CAutoLaunchApp::ExitInstance()
	{							// CAutoLaunchApp::ExitInstance
	CloseHandle(m_hMutex);
	return 0;
	}							// CAutoLaunchApp::ExitInstance

#endif // NOT NTSERVICE

//=============================================================================
//=============================================================================
//                  B O T H   C O N F I G U R A T I O N S                   
//=============================================================================
//=============================================================================

VOID CAutoLaunch::EnumerateExistingDevices(const GUID* guid)
	{							// CAutoLaunch::EnumerateExistingDevices
	HDEVINFO info = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
	if (info == INVALID_HANDLE_VALUE)
		return;

	SP_INTERFACE_DEVICE_DATA ifdata;
	ifdata.cbSize = sizeof(ifdata);
	DWORD devindex;
	for (devindex = 0; SetupDiEnumDeviceInterfaces(info, NULL, guid, devindex, &ifdata); ++devindex)
		{						// for each device
		DWORD needed;
		SetupDiGetDeviceInterfaceDetail(info, &ifdata, NULL, 0, &needed, NULL);

		PSP_INTERFACE_DEVICE_DETAIL_DATA detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(needed);
		if (!detail)
			continue;
		detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

		SP_DEVINFO_DATA devdata = {sizeof(SP_DEVINFO_DATA)};

		if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, detail, needed, NULL, &devdata))
			{						// can't get detail info
			free((PVOID) detail);
			continue;
			}						// can't get detail info

		CString devname = detail->DevicePath;
		free((PVOID) detail);
		OnNewDevice(devname, info, &devdata);
		}						// for each device

	SetupDiDestroyDeviceInfoList(info);
	}							// CAutoLaunch::EnumerateExistingDevices

///////////////////////////////////////////////////////////////////////////////

DWORD CAutoLaunch::HandleDeviceChange(DWORD evtype, _DEV_BROADCAST_HEADER *dbhdr)
	{							// CAutoLaunch::HandleDeviceChange
	if (!dbhdr || dbhdr->dbcd_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
		return 0;				// ignore all other events

	// Extract symbolic link name of the device that's arrived. In NT, the service always
	// receives the UNICODE version of the notification structure

#ifdef NTSERVICE
	PDEV_BROADCAST_DEVICEINTERFACE_W p = (PDEV_BROADCAST_DEVICEINTERFACE_W) dbhdr;
#else
	PDEV_BROADCAST_DEVICEINTERFACE p = (PDEV_BROADCAST_DEVICEINTERFACE) dbhdr;
#endif

	CString devname = p->dbcc_name;

	// If device is departing, remove its name from our list

	if (evtype == DBT_DEVICEREMOVECOMPLETE)
		{						// device removed
		for (int i = 0; i < m_devices.GetSize(); )
			if (devname.CompareNoCase(m_devices[i]) == 0)
				m_devices.RemoveAt(i);
			else
				++i;
		}						// device removed

	// If device is arriving, check for the need to launch a command automatically

	else if (evtype == DBT_DEVICEARRIVAL)
		{						// interface arrival event
		HDEVINFO info = SetupDiCreateDeviceInfoList(NULL, NULL);
		if (info == INVALID_HANDLE_VALUE)
			return 0;
		SP_DEVICE_INTERFACE_DATA ifdata = {sizeof(SP_DEVICE_INTERFACE_DATA)};
		SP_DEVINFO_DATA devdata = {sizeof(SP_DEVINFO_DATA)};

		if (SetupDiOpenDeviceInterface(info, devname, 0, &ifdata)
			&& (SetupDiGetDeviceInterfaceDetail(info, &ifdata, NULL, 0, NULL, &devdata)
			|| GetLastError() == ERROR_INSUFFICIENT_BUFFER))
			OnNewDevice(devname, info, &devdata);

		SetupDiDestroyDeviceInfoList(info);
		}						// interface arrival event

	return 0;
	}							// CAutoLaunch::HandleDeviceChange

///////////////////////////////////////////////////////////////////////////////

void CAutoLaunch::OnNewDevice(const CString& devname, HDEVINFO info, PSP_DEVINFO_DATA devdata)
	{							// CAutoLaunch::OnNewDevice

	// Prevent duplicate launches

	for (int i = 0; i < m_devices.GetSize(); )
		if (devname.CompareNoCase(m_devices[i]) == 0)
			return;
		else
			++i;
	m_devices.Add(devname);

	// Open the hardware key for this device

	HKEY hkey = SetupDiOpenDevRegKey(info, devdata, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
	if (!hkey)
		{						// can't open key
		CString msg;
		msg.Format(_T("Can't open registry key for %s"), (LPCTSTR) devname);
		Log(msg);
		return;
		}						// can't open key

	// Get the AutoLaunch parameter from the registry

	DWORD junk;
	TCHAR buffer[_MAX_PATH];
	DWORD size = sizeof(buffer);
	CString Command;

	if (RegQueryValueEx(hkey, _T("AutoLaunch"), NULL, &junk, (LPBYTE) buffer, &size) != 0)
		{						// no AutoLaunch
		CString msg;
		msg.Format(_T("No AutoLaunch parameter for %s"), (LPCTSTR) devname);
		Log(msg);
		RegCloseKey(hkey);
		return;
		}						// no AutoLaunch
	Command = buffer;

	// Determine the device's friendly name

	CString FriendlyName;
	size = sizeof(buffer);
	if (!SetupDiGetDeviceRegistryProperty(info, devdata, SPDRP_FRIENDLYNAME, NULL, (PBYTE) buffer, sizeof(buffer), NULL)
		|| !SetupDiGetDeviceRegistryProperty(info, devdata, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
		buffer[0] = 0;	// no friendly name or description
	FriendlyName.Format(_T("\"%s\""), buffer);

	RegCloseKey(hkey);

	// Format and invoke the command

	ExpandEnvironmentStrings(Command, buffer, arraysize(buffer));
	CString name;
	name.Format(_T("\"%s\""), (LPCTSTR) devname);
	Command.Format(buffer, (LPCTSTR) name, (LPCTSTR) FriendlyName);

	STARTUPINFO si = {sizeof(STARTUPINFO)};
	si.lpDesktop = _T("WinSta0\\Default"); // name of interactive session's desktop
	si.wShowWindow = SW_SHOW;
	
	PROCESS_INFORMATION pi;
	if (CreateProcess(NULL, (LPTSTR) (LPCTSTR) Command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
		{						// launched okay
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		Log(Command);
		}						// launched okay
	else
		{						// error launching command
		CString msg;
		msg.Format(_T("Error %d trying to execute %s"), GetLastError(), (LPCTSTR) Command);
		Log(msg);
		}						// error launching command
	}							// CAutoLaunch::OnNewDevice

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -