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

📄 autolaunch.cpp

📁 Programming the Microsoft Windows driver model.2nd 随书光盘。内有很多作者送的实用工具和随书源码。WDM编程
💻 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 + -