📄 linkdlg.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 + -