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

📄 linkdlg.c

📁 Virtual Floppy Driver
💻 C
字号:
/*
	linkdlg.c

	Virtual Floppy Disk drive control panel
    Copyright (C) 2003 Kenji Kato
*/

#include "sysincl.h"
#include "vfdutil.h"
#include "vfdwin.h"
#include "resource.h"

//	dialog message handlers

static BOOL OnLinkInitDialog(HWND hDlg);
static void OnLinkDestroy();
static void OnLinkCommand(HWND hDlg, UINT uID, HWND hCtrl);

//	other internal functions

static void ApplyShortcuts(HWND hDlg);
static void AdjustButtons(HWND hDlg);

static LPTSTR SearchLink(HWND hDlg, int folder, BOOL mount);
static LPTSTR CreateVfdLink(HWND hDlg, int folder, BOOL mount, int desc_id);

static BOOL GetFolderPath(HWND hDlg, int folder, LPTSTR link);
static HRESULT LoadLink(IShellLink *pLink, LPCTSTR path);
static void GetLinkParams(IShellLink *pLink, LPTSTR path, LPTSTR args);

static HRESULT CreateLink(
	LPCTSTR link_path,
	LPCTSTR target_path,
	LPCTSTR arguments,
	LPCTSTR description,
	int icon_index);

static void DeleteVfdLink(LPTSTR *path);

//
//	link paths storage
//

static LPTSTR pMntDesktop	= NULL;
static LPTSTR pMntSendTo	= NULL;
static LPTSTR pCfgDesktop	= NULL;
static LPTSTR pCfgStartMenu	= NULL;

//
//	Shortcut page Dialog Procedure
//

BOOL CALLBACK LinkProc(
	HWND hDlg,
	UINT msg,
	WPARAM wParam,
	LPARAM lParam) 
{
    switch (msg) {
	case WM_INITDIALOG:
		if (!OnLinkInitDialog(hDlg)) {
			DestroyWindow(hDlg);
		}
		return 0;

	case WM_DESTROY:
		OnLinkDestroy();
		return 0;

	case WM_COMMAND:
		OnLinkCommand(hDlg, LOWORD(wParam), (HWND)lParam);
		return 0;
    } 

    return 0; 
} 

//
//	Initialize Shortcut dialog
//

BOOL OnLinkInitDialog(HWND hDlg)
{
	//	Search Shortcut Link

	pMntDesktop		= SearchLink(hDlg, CSIDL_DESKTOPDIRECTORY, TRUE);
	pCfgDesktop		= SearchLink(hDlg, CSIDL_DESKTOPDIRECTORY, FALSE);
	pMntSendTo		= SearchLink(hDlg, CSIDL_SENDTO, TRUE);
	pCfgStartMenu	= SearchLink(hDlg, CSIDL_STARTMENU, FALSE);

	AdjustButtons(hDlg);

	return TRUE;
}
		
//
//	called when link dialog is destroyed
//

void OnLinkDestroy()
{
	if (pMntDesktop) {
		free(pMntDesktop);
		pMntDesktop = NULL;
	}
	if (pMntSendTo) {
		free(pMntSendTo);
		pMntSendTo = NULL;
	}
	if (pCfgDesktop) {
		free(pCfgDesktop);
		pCfgDesktop = NULL;
	}
	if (pCfgStartMenu) {
		free(pCfgStartMenu);
		pCfgStartMenu = NULL;
	}
}

//
//	called when a button is clicked
//

void OnLinkCommand(HWND hDlg, UINT uID, HWND hCtrl)
{
	if (uID == IDC_LINK_APPLY) {

		//	apply button is clicked

		ApplyShortcuts(hDlg);
		AdjustButtons(hDlg);

		SetFocus(GetDlgItem(hDlg, IDC_LINK_MNT_DESKTOP));
		EnableWindow(hCtrl, FALSE);
		SendMessage(hCtrl, BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
	}
	else {
		BOOL new_mnt_dt, new_mnt_st, new_cfg_dt, new_cfg_sm,
			old_mnt_dt, old_mnt_st, old_cfg_dt, old_cfg_sm;

		new_mnt_dt = (IsDlgButtonChecked(hDlg, IDC_LINK_MNT_DESKTOP) == BST_CHECKED);
		new_mnt_st = (IsDlgButtonChecked(hDlg, IDC_LINK_MNT_SENDTO) == BST_CHECKED);
		new_cfg_dt = (IsDlgButtonChecked(hDlg, IDC_LINK_CFG_DESKTOP) == BST_CHECKED);
		new_cfg_sm = (IsDlgButtonChecked(hDlg, IDC_LINK_CFG_STARTMENU) == BST_CHECKED);

		old_mnt_dt = (pMntDesktop != NULL);
		old_mnt_st = (pMntSendTo != NULL);
		old_cfg_dt = (pCfgDesktop != NULL);
		old_cfg_sm = (pCfgStartMenu != NULL);

		EnableWindow(GetDlgItem(hDlg, IDC_LINK_APPLY), 
			new_mnt_dt != old_mnt_dt ||
			new_mnt_st != old_mnt_st ||
			new_cfg_dt != old_cfg_dt ||
			new_cfg_sm != old_cfg_sm
		);
	}
}

//
//	create / delete shortcuts according to checkbox state
//

void ApplyShortcuts(HWND hDlg)
{
	BOOL new_mnt_dt, new_mnt_st, new_cfg_dt, new_cfg_sm;

	new_mnt_dt = (IsDlgButtonChecked(hDlg, IDC_LINK_MNT_DESKTOP) == BST_CHECKED);
	new_mnt_st = (IsDlgButtonChecked(hDlg, IDC_LINK_MNT_SENDTO) == BST_CHECKED);
	new_cfg_dt = (IsDlgButtonChecked(hDlg, IDC_LINK_CFG_DESKTOP) == BST_CHECKED);
	new_cfg_sm = (IsDlgButtonChecked(hDlg, IDC_LINK_CFG_STARTMENU) == BST_CHECKED);

	//	Delete unchecked shortcuts
	if (!new_mnt_dt && pMntDesktop) {
		DeleteVfdLink(&(pMntDesktop));
	}

	if (!new_mnt_st && pMntSendTo) {
		DeleteVfdLink(&(pMntSendTo));
	}

	if (!new_cfg_dt && pCfgDesktop) {
		DeleteVfdLink(&(pCfgDesktop));
	}

	if (!new_cfg_sm && pCfgStartMenu) {
		DeleteVfdLink(&(pCfgStartMenu));
	}

	// Create checked shortcuts

	if (new_mnt_dt && !pMntDesktop) {
		pMntDesktop = CreateVfdLink(
			hDlg, CSIDL_DESKTOPDIRECTORY, TRUE, IDS_LINK_DESC_MNT_DT);
	}

	if (new_mnt_st && !pMntSendTo) {
		pMntSendTo = CreateVfdLink(
			hDlg, CSIDL_SENDTO, TRUE, IDS_LINK_DESC_MNT_ST);
	}

	if (new_cfg_dt && !pCfgDesktop) {
		pCfgDesktop = CreateVfdLink(
			hDlg, CSIDL_DESKTOPDIRECTORY, FALSE, IDS_LINK_DESC_CONFIG);
	}

	if (new_cfg_sm && !pCfgStartMenu) {
		pCfgStartMenu = CreateVfdLink(
			hDlg, CSIDL_STARTMENU, FALSE, IDS_LINK_DESC_CONFIG);
	}
}

//
//	adjust checkbox state according to existing shortcuts
//

void AdjustButtons(HWND hDlg)
{
	CheckDlgButton(hDlg, IDC_LINK_MNT_DESKTOP, pMntDesktop ? BST_CHECKED : BST_UNCHECKED);
	CheckDlgButton(hDlg, IDC_LINK_CFG_DESKTOP, pCfgDesktop ? BST_CHECKED : BST_UNCHECKED);
	CheckDlgButton(hDlg, IDC_LINK_MNT_SENDTO, pMntSendTo ? BST_CHECKED : BST_UNCHECKED);
	CheckDlgButton(hDlg, IDC_LINK_CFG_STARTMENU, pCfgStartMenu ? BST_CHECKED : BST_UNCHECKED);
}

//
//	search shortcuts for this application in a system folder
//

LPTSTR SearchLink(
	HWND	hDlg,
	int		folder,
	BOOL	mount)
{
	TCHAR		link_path[MAX_PATH];
	int			link_path_len;
	WIN32_FIND_DATA find;
	HANDLE		hFind;
	IShellLink	*pLink;
	HRESULT		res;
	BOOL		match = FALSE;
	
	if (!GetFolderPath(hDlg, folder, link_path)) {
		return NULL;
	}

	link_path_len = strlen(link_path);

	//	search files with *.lnk extension

	strcpy(link_path + link_path_len, "\\*.lnk");

	hFind = FindFirstFile(link_path, &find);

	if (hFind == INVALID_HANDLE_VALUE) {
		if (GetLastError() != ERROR_FILE_NOT_FOUND) {
			DEBUG_TRACE1(
				"SearchLink : FindFirstFile - %s", ErrMsg(GetLastError()));
		}
		//	no *.lnk file
		return NULL;
	}

	// create IShellLink object interface

	res = CoCreateInstance(&CLSID_ShellLink, NULL,
			CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID *)&pLink);

	if (!SUCCEEDED(res)) {
		FindClose(hFind);

		DEBUG_TRACE1(
			"SearchLink : CoCreateInstance - %s", ErrMsg(res));

		return NULL;
	}

	//	keep folder path and a trailing \ character

	link_path_len++;

	do {
		// compose the shortcut file's full path

		strcpy(link_path + link_path_len, find.cFileName);

		res = LoadLink(pLink, link_path);

		if (SUCCEEDED(res)) {
			char path[MAX_PATH], args[MAX_PATH];

			GetLinkParams(pLink, path, args);

			if (strstr(path, VFD_APP_FILENAME)) {
				BOOL arg_mount = (strnicmp(args, VFD_MOUNT_SWITCH, sizeof(VFD_MOUNT_SWITCH) - 1) == 0);

				if (mount == arg_mount) {
					match = TRUE;
					break;
				}
			}
		}
		else {
			break;
		}
	}
	while (FindNextFile(hFind, &find));

	pLink->lpVtbl->Release(pLink);

	FindClose(hFind);

	if (match) {
		LPTSTR p = (LPTSTR)malloc(strlen(link_path) + 1);

		if (!p) {
			DEBUG_TRACE2(
				"SearchLink : malloc(%lu) - %s",
				strlen(link_path) + 1, ErrMsg(GetLastError()));
		}
		else {
			strcpy(p, link_path);
		}
		
		return p;
	}

	return NULL;
}

//
//	load link object from file object
//

HRESULT LoadLink(
	IShellLink *pLink,
	LPCTSTR path)
{
	IPersistFile *pFile;
	HRESULT		res;
	WCHAR		wsz[MAX_PATH];

	// Get a pointer to the IPersistFile interface.
	res = pLink->lpVtbl->QueryInterface(pLink, &IID_IPersistFile, (LPVOID *)&pFile);

	if (!SUCCEEDED(res)) {
		DEBUG_TRACE1(
			"LoadLink : pLink->QueryInterface - %s", ErrMsg(res));

		return res;
	}

	// convert path into Unicode 
	if (!MultiByteToWideChar(CP_OEMCP, 0, path, -1, wsz, MAX_PATH)) {
		DWORD err = GetLastError();

		DEBUG_TRACE1(
			"LoadLink : MultiByteToWideChar - %s", ErrMsg(err));

		return HRESULT_FROM_WIN32(err);
	}

	// Load the shortcut.
	res = pFile->lpVtbl->Load(pFile, wsz, STGM_READ);

	// Interface no longer neccessary
	pFile->lpVtbl->Release(pFile);

	if (!SUCCEEDED(res)) {
		DEBUG_TRACE1(
			"LoadLink : pFile->Load - %s", ErrMsg(res));
	}

	return res;
}

//
//	get parameters from a link object
//

void GetLinkParams(
	IShellLink *pLink,
	LPTSTR	path,
	LPTSTR	args)
{
	HRESULT res;

	*path = '\0';
	*args = '\0';

	res = pLink->lpVtbl->GetPath(pLink, path, MAX_PATH, NULL, SLGP_UNCPRIORITY);

	if (!SUCCEEDED(res)) {
		DEBUG_TRACE1(
			"GetLinkParams : pLink->GetPath - %s", ErrMsg(res));

		return;
	}

	while (*path) {
		*path = (char)tolower(*path);
		path++;
	}

	res = pLink->lpVtbl->GetArguments(pLink, args, MAX_PATH);

	if (!SUCCEEDED(res)) {
		DEBUG_TRACE1(
			"GetLinkParams : pLink->GetArguments - %s", ErrMsg(res));

		return;
	}

	while (*args) {
		*args = (char)tolower(*args);
		args++;
	}

	return;
}

//
//	create a shortcut link (preparation)
//

LPTSTR CreateVfdLink (
	HWND	hDlg,
	int		folder,
	BOOL	mount,
	int		desc_id)
{ 
	char link_path[MAX_PATH], exe_path[MAX_PATH], desc_str[MAX_PATH];
	HRESULT res;

	//	create fullpath for the link

	if (!GetFolderPath(hDlg, folder, link_path)) {
		return NULL;
	}

	strcat(link_path, "\\");

	if (mount) {
		strcat(link_path, VFD_APP_NAME);
	}
	else {
		int len = strlen (link_path);

		if (!LoadString(NULL, IDS_APP_NAME, &link_path[len], sizeof(link_path) - len)) {
			DEBUG_TRACE1(
				"CreateVfdLink : LoadString(IDS_APP_NAME) - %s",
				ErrMsg(GetLastError()));

			//	use fallback name
			strcpy(&link_path[len], VFD_CFG_LINK_NAME);
		}
	}

	strcat(link_path, ".lnk");

	//	get link target (current application's full path) and description

	if (!GetModuleFileName(hAppInstance, exe_path, sizeof(exe_path))) {
		DEBUG_TRACE1(
			"CreateVfdLink : GetModuleFileName - %s",
			ErrMsg(GetLastError()));

		return NULL;
	}

	//	load link description string

	if (!LoadString(NULL, desc_id, desc_str, sizeof(desc_str))) {
		DEBUG_TRACE2(
			"CreateVfdLink : LoadString(%u) - %s",
			desc_id, ErrMsg(GetLastError()));

		// this is not fatal
	}

	//	Create a shortcut link

	res = CreateLink(
		link_path,
		exe_path,
		mount ? VFD_MOUNT_SWITCH : NULL,
		desc_str,
		mount ? VFD_ICON_IDX_MOUNT : VFD_ICON_IDX_CONFIG);

	if (SUCCEEDED(res)) {
		LPTSTR p;

		// link was actually created so let the shell know it
		SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, link_path, NULL);

		p = (LPTSTR)malloc(strlen(link_path) + 1);

		if (!p) {
			DEBUG_TRACE2(
				"CreateVfdLink : malloc(%u) - %s",
				strlen(link_path) + 1, ErrMsg(GetLastError()));
		}
		else {
			strcpy(p, link_path);
		}
		
		return p;
	}

	return NULL;
}

//
//	delete shortcut file
//

void DeleteVfdLink(LPTSTR *path)
{
	if (DeleteFile(*path) || GetLastError() == ERROR_FILE_NOT_FOUND) {
		SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, *path, NULL);
		free(*path);
		*path = NULL;
	}
	else {
		DEBUG_TRACE2(
			"DeleteVfdLink : DeleteFile(%s) - %s",
			*path, ErrMsg(GetLastError()));
	}
}

//
//	get path of a system special folder
//

BOOL GetFolderPath(
	HWND	hDlg,
	int		folder,
	LPTSTR	path)
{
   	LPMALLOC pMalloc;
	LPITEMIDLIST pidl;
	BOOL	ret;
	HRESULT res;

	res = SHGetSpecialFolderLocation(hDlg, folder, &pidl);

	if (!SUCCEEDED(res)) {
		DEBUG_TRACE2(
			"GetFolderPath : SHGetSpecialFolderLocation(%d) - %s",
			folder, ErrMsg(res));

		return FALSE;
	}

	ret = SHGetPathFromIDList(pidl, path);

	if (!ret) {
		DEBUG_TRACE2(
			"GetFolderPath : SHGetPathFromIDList(%d) - %s",
			folder, ErrMsg(GetLastError()));
	}

	res = SHGetMalloc(&pMalloc);

	if (SUCCEEDED(res)) {
		pMalloc->lpVtbl->Free(pMalloc, pidl);
		pMalloc->lpVtbl->Release(pMalloc);
	}
	else {
		DEBUG_TRACE1(
			"GetFolderPath : SHGetMalloc - %s", ErrMsg(res));
	}

	return ret;
}

//
//	create a shortcut link
//
HRESULT CreateLink(
	LPCTSTR link_path,
	LPCTSTR target_path,
	LPCTSTR arguments,
	LPCTSTR description,
	int icon_index)
{
	IShellLink	*pLink;
	IPersistFile *pFile; 
	HRESULT		res;
	WCHAR		wsz[MAX_PATH]; 

	// Get a pointer to the IShellLink interface. 
	res = CoCreateInstance(&CLSID_ShellLink, NULL, 
		CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID *)&pLink);

	if (!SUCCEEDED(res)) { 
		DEBUG_TRACE1(
			"CreateLink : CoCreateInstance - %s", ErrMsg(res));

		return res;
	}

	// Set link properties
	if (target_path) {
		res = pLink->lpVtbl->SetPath(pLink, target_path);

		if (!SUCCEEDED(res)) { 
			DEBUG_TRACE1(
				"CreateLink : pLink->SetPath - %s", ErrMsg(res));

			goto cleanup;
		}
	}

	if (arguments) {
		pLink->lpVtbl->SetArguments(pLink, arguments); 

		if (!SUCCEEDED(res)) { 
			DEBUG_TRACE1(
				"CreateLink : pLink->SetArguments - %s", ErrMsg(res));

			goto cleanup;
		}
	}

	if (description) {
		pLink->lpVtbl->SetDescription(pLink, description);

		if (!SUCCEEDED(res)) { 
			DEBUG_TRACE1(
				"CreateLink : pLink->SetDescription - %s", ErrMsg(res));

			goto cleanup;
		}
	}

	if (icon_index) {
		pLink->lpVtbl->SetIconLocation(pLink, target_path, icon_index);

		if (!SUCCEEDED(res)) { 
			DEBUG_TRACE1(
				"CreateLink : pLink->SetIconLocation - %s", ErrMsg(res));

			goto cleanup;
		}
	}

   // Query IShellLink for the IPersistFile interface for saving the 
   // shortcut in persistent storage. 

	res = pLink->lpVtbl->QueryInterface(pLink, &IID_IPersistFile, (LPVOID*)&pFile); 

	if (!SUCCEEDED(res)) { 
		DEBUG_TRACE1(
			"CreateLink : pLink->QueryInterface - %s", ErrMsg(res));

		goto cleanup;
	}

	// Ensure that the string is Unicode. 

	if (MultiByteToWideChar(CP_OEMCP, 0, link_path, -1, wsz, MAX_PATH)) {
		// Save the link by calling IPersistFile::Save. 
		res = pFile->lpVtbl->Save(pFile, wsz, TRUE);

		if (!SUCCEEDED(res)) {
			DEBUG_TRACE1(
				"CreateLink : pFile->Save - %s", ErrMsg(res));
		}
	}
	else {
		res = HRESULT_FROM_WIN32(GetLastError());

		DEBUG_TRACE1(
			"CreateLink : MultiByteToWideChar - %s", ErrMsg(GetLastError()));
	} 

	pFile->lpVtbl->Release(pFile); 

cleanup:
	pLink->lpVtbl->Release(pLink);

	return res;
}

// End Of File

⌨️ 快捷键说明

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