You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1172 lines
27 KiB
1172 lines
27 KiB
/*
|
|
* propsht.cpp - IPropSheetExt implementation for CFusionShortcut class.
|
|
*/
|
|
|
|
|
|
|
|
// * NOTE!!: this code is incomplete. Also error checking (any leak?),
|
|
// * restructuring (for better coding/efficiency) to be done.
|
|
// * Make 'Get'/'Set' private and use 'friend'?
|
|
|
|
|
|
//BUGBUG: need wrappers around calls to m_pIdentity->SetAttribute() to also call Dirty(TRUE)...
|
|
|
|
|
|
// * this file uses CharNext etc as it needs User32 anyway *
|
|
|
|
/* Headers
|
|
**********/
|
|
|
|
#include "project.hpp"
|
|
|
|
#include <prsht.h>
|
|
|
|
#include "shellres.h"
|
|
|
|
extern "C" WINSHELLAPI int WINAPI PickIconDlg(HWND hwnd, LPWSTR pwzIconPath, UINT cbIconPath, int *piIconIndex);
|
|
|
|
extern HINSTANCE g_DllInstance;
|
|
|
|
/* Types
|
|
********/
|
|
|
|
// Fusion Shortcut property sheet data
|
|
|
|
typedef enum _fusshcutpropsheetpgs
|
|
{
|
|
FUSIONSHCUT_PS_SHCUT_PAGE = 0x0000,
|
|
FUSIONSHCUT_PS_REF_PAGE = 0x0001,
|
|
|
|
ALL_FUSIONSHCUT_PS_PAGES
|
|
}
|
|
FUSIONSHCUTPSPAGES;
|
|
|
|
typedef struct _fsps
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
|
|
WCHAR rgchIconFile[MAX_PATH];
|
|
|
|
int niIcon;
|
|
|
|
FUSIONSHCUTPSPAGES eCurPage;
|
|
}
|
|
FSPS;
|
|
DECLARE_STANDARD_TYPES(FSPS);
|
|
|
|
typedef FSPS* PFSPS;
|
|
|
|
/* Module Constants
|
|
*******************/
|
|
|
|
// Tray notification window class
|
|
|
|
//copied from shell32!
|
|
#define WNDCLASS_TRAYNOTIFY L"Shell_TrayWnd" //internal_win40
|
|
const WCHAR s_cwzTrayNotificationClass[] = WNDCLASS_TRAYNOTIFY;
|
|
|
|
// HACKHACK: WMTRAY_SCREGISTERHOTKEY and WMTRAY_SCUNREGISTERHOTKEY are stolen
|
|
// from shelldll\link.c.
|
|
typedef const UINT CUINT;
|
|
CUINT WMTRAY_SCREGISTERHOTKEY = (WM_USER + 233);
|
|
CUINT WMTRAY_SCUNREGISTERHOTKEY = (WM_USER + 234);
|
|
|
|
// show commands - N.b., the order of these constants must match the order of
|
|
// the corresponding IDS_ string table constants.
|
|
|
|
const UINT s_ucMaxShowCmdLen = MAX_PATH;
|
|
const UINT s_ucMaxTypeLen = TYPESTRINGLENGTH;
|
|
|
|
const int s_rgnShowCmds[] =
|
|
{
|
|
SW_SHOWNORMAL,
|
|
SW_SHOWMINNOACTIVE,
|
|
SW_SHOWMAXIMIZED
|
|
};
|
|
|
|
|
|
/*
|
|
** ExtractFileName()
|
|
**
|
|
** Extracts the file name from a path name.
|
|
**
|
|
** Arguments: pcwzPathName - path string from which to extract file name
|
|
**
|
|
** Returns: Pointer to file name in path string.
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
#define BACKSLASH L'/'
|
|
#define SLASH L'\\'
|
|
#define COLON L':'
|
|
#define IS_SLASH(ch) ((ch) == SLASH || (ch) == BACKSLASH)
|
|
PCWSTR ExtractFileName(PCWSTR pcwzPathName)
|
|
{
|
|
PCWSTR pcwzLastComponent;
|
|
PCWSTR pcwz;
|
|
|
|
for (pcwzLastComponent = pcwz = pcwzPathName; *pcwz; pcwz = CharNext(pcwz))
|
|
{
|
|
if (IS_SLASH(*pcwz) || *pcwz == COLON)
|
|
pcwzLastComponent = CharNext(pcwz);
|
|
}
|
|
|
|
ASSERT(IsValidPath(pcwzLastComponent));
|
|
|
|
return(pcwzLastComponent);
|
|
}
|
|
|
|
/***************************** Private Functions *****************************/
|
|
|
|
|
|
UINT CALLBACK FSPSCallback(HWND hwnd, UINT uMsg,
|
|
LPPROPSHEETPAGE ppsp)
|
|
{
|
|
// this is called after FSPS_DlgProc WM_DESTROY (ie. FSPS_Destroy)
|
|
// this func should do the frees/releases
|
|
|
|
UINT uResult = TRUE;
|
|
PFSPS pfsps = (PFSPS)(ppsp->lParam);
|
|
|
|
// uMsg may be any value.
|
|
|
|
ASSERT(! hwnd ||
|
|
IS_VALID_HANDLE(hwnd, WND));
|
|
|
|
switch (uMsg)
|
|
{
|
|
case PSPCB_CREATE:
|
|
// from MSDN: A dialog box for a page is being created.
|
|
// Return nonzero to allow it to be created, or zero to prevent it.
|
|
break;
|
|
|
|
case PSPCB_RELEASE:
|
|
// ???? need checking if NULL
|
|
|
|
pfsps->pfusshcut->Release();
|
|
|
|
// free the FSPS structure, this is created in AddFSPS
|
|
// delete only after the ref is removed
|
|
delete pfsps;
|
|
ppsp->lParam = NULL;
|
|
|
|
break;
|
|
|
|
default:
|
|
// ignore other msg - unhandled
|
|
break;
|
|
}
|
|
|
|
return(uResult);
|
|
}
|
|
|
|
|
|
void SetFSPSIcon(HWND hdlg, HICON hicon)
|
|
{
|
|
HICON hiconOld;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
ASSERT(IS_VALID_HANDLE(hicon, ICON));
|
|
|
|
hiconOld = (HICON)SendDlgItemMessage(hdlg, IDD_ICON, STM_SETICON,
|
|
(WPARAM)hicon, 0);
|
|
|
|
if (hiconOld)
|
|
DestroyIcon(hiconOld);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSFileNameAndIcon(HWND hdlg)
|
|
{
|
|
HRESULT hr;
|
|
CFusionShortcut* pfusshcut;
|
|
WCHAR rgchFile[MAX_PATH];
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
hr = pfusshcut->GetCurFile(rgchFile, sizeof(rgchFile) / sizeof(WCHAR));
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
SHFILEINFO shfi;
|
|
DWORD_PTR dwResult;
|
|
|
|
dwResult = SHGetFileInfo(rgchFile, 0, &shfi, sizeof(shfi),
|
|
(SHGFI_DISPLAYNAME | SHGFI_ICON));
|
|
|
|
if (dwResult)
|
|
{
|
|
LPWSTR pwzFileName;
|
|
|
|
pwzFileName = (LPWSTR)ExtractFileName(shfi.szDisplayName);
|
|
|
|
EVAL(SetDlgItemText(hdlg, IDD_NAME, pwzFileName));
|
|
|
|
SetFSPSIcon(hdlg, shfi.hIcon);
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
|
|
if (hr != S_OK)
|
|
EVAL(SetDlgItemText(hdlg, IDD_NAME, g_cwzEmptyString));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSWorkingDirectory(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
WCHAR rgchWorkingDirectory[MAX_PATH];
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
hr = pfusshcut->GetWorkingDirectory(rgchWorkingDirectory,
|
|
sizeof(rgchWorkingDirectory) / sizeof(WCHAR));
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_START_IN, rgchWorkingDirectory));
|
|
}
|
|
else
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_START_IN, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void InitFSPSHotkey(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
WORD wHotkey;
|
|
HRESULT hr;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
// Set hotkey combinations.
|
|
|
|
SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_SETRULES,
|
|
(HKCOMB_NONE | HKCOMB_A | HKCOMB_C | HKCOMB_S),
|
|
(HOTKEYF_CONTROL | HOTKEYF_ALT));
|
|
|
|
// Set current hotkey.
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
hr = pfusshcut->GetHotkey(&wHotkey);
|
|
SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_SETHOTKEY, wHotkey, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void InitFSPSShowCmds(HWND hdlg)
|
|
{
|
|
int niShowCmd;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
for (niShowCmd = IDS_SHOW_NORMAL;
|
|
niShowCmd <= IDS_SHOW_MAXIMIZED;
|
|
niShowCmd++)
|
|
{
|
|
WCHAR rgchShowCmd[s_ucMaxShowCmdLen];
|
|
|
|
if (LoadString(g_DllInstance, niShowCmd, rgchShowCmd, //MLLoadStringA
|
|
s_ucMaxShowCmdLen))//sizeof(rgchShowCmd)))
|
|
{
|
|
SendDlgItemMessage(hdlg, IDD_SHOW_CMD, CB_ADDSTRING, 0,
|
|
(LPARAM)rgchShowCmd);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSShowCmd(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
int nShowCmd;
|
|
int i;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
pfusshcut->GetShowCmd(&nShowCmd);
|
|
|
|
for (i = 0; i < ARRAY_ELEMENTS(s_rgnShowCmds); i++)
|
|
{
|
|
if (s_rgnShowCmds[i] == nShowCmd)
|
|
break;
|
|
}
|
|
|
|
if (i >= ARRAY_ELEMENTS(s_rgnShowCmds))
|
|
{
|
|
ASSERT(i == ARRAY_ELEMENTS(s_rgnShowCmds));
|
|
|
|
i = 0; // default is 0 == 'normal'
|
|
}
|
|
|
|
SendDlgItemMessage(hdlg, IDD_SHOW_CMD, CB_SETCURSEL, i, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSFriendlyName(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
WCHAR rgchString[DISPLAYNAMESTRINGLENGTH];
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
hr = pfusshcut->GetDescription(rgchString, sizeof(rgchString) / sizeof(WCHAR));
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_DISPLAY_NAME, rgchString));
|
|
}
|
|
else
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_DISPLAY_NAME, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSName(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
DWORD ccString = 0;
|
|
LPWSTR pwzString = NULL;
|
|
LPASSEMBLY_IDENTITY pId = NULL;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
|
|
{
|
|
hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzString, &ccString);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_NAME, pwzString));
|
|
delete [] pwzString;
|
|
}
|
|
|
|
pId->Release();
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_NAME, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSVersion(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
DWORD ccString = 0;
|
|
LPWSTR pwzString = NULL;
|
|
LPASSEMBLY_IDENTITY pId = NULL;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
|
|
{
|
|
hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION, &pwzString, &ccString);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_VERSION, pwzString));
|
|
delete [] pwzString;
|
|
}
|
|
|
|
pId->Release();
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_VERSION, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSCulture(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
DWORD ccString = 0;
|
|
LPWSTR pwzString = NULL;
|
|
LPASSEMBLY_IDENTITY pId = NULL;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
|
|
{
|
|
hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE, &pwzString, &ccString);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_CULTURE, pwzString));
|
|
delete [] pwzString;
|
|
}
|
|
|
|
pId->Release();
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_CULTURE, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSPKT(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
DWORD ccString = 0;
|
|
LPWSTR pwzString = NULL;
|
|
LPASSEMBLY_IDENTITY pId = NULL;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
|
|
{
|
|
hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzString, &ccString);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_PKT, pwzString));
|
|
delete [] pwzString;
|
|
}
|
|
|
|
pId->Release();
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_PKT, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSCodebase(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
WCHAR rgchString[MAX_URL_LENGTH];
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
hr = pfusshcut->GetCodebase(rgchString, sizeof(rgchString) / sizeof(WCHAR));
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_CODEBASE, rgchString));
|
|
}
|
|
else
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_CODEBASE, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSEntrypoint(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
WCHAR rgchString[MAX_PATH];
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
hr = pfusshcut->GetPath(rgchString, sizeof(rgchString) / sizeof(WCHAR), NULL, 0);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_ENTRYPOINT, rgchString));
|
|
}
|
|
else
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_ENTRYPOINT, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void SetFSPSType(HWND hdlg)
|
|
{
|
|
CFusionShortcut* pfusshcut;
|
|
HRESULT hr;
|
|
DWORD ccString = 0;
|
|
LPWSTR pwzString = NULL;
|
|
LPASSEMBLY_IDENTITY pId = NULL;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
|
|
{
|
|
hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_TYPE, &pwzString, &ccString);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_TYPE, pwzString));
|
|
delete [] pwzString;
|
|
}
|
|
|
|
pId->Release();
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
EVAL(SetDlgItemText(hdlg, IDD_TYPE, g_cwzEmptyString));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL FSPS_InitDialog(HWND hdlg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
// wparam may be any value.
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
// this set PROPSHEETPAGE struct to DWLP_USER
|
|
SetWindowLongPtr(hdlg, DWLP_USER, lparam);
|
|
|
|
// Initialize control contents.
|
|
|
|
if (((PFSPS)(((PROPSHEETPAGE*)lparam)->lParam))->eCurPage == FUSIONSHCUT_PS_SHCUT_PAGE)
|
|
{
|
|
SetFSPSFileNameAndIcon(hdlg);
|
|
|
|
// note: need limits on all editbox!
|
|
SetFSPSFriendlyName(hdlg);
|
|
|
|
SendDlgItemMessage(hdlg, IDD_CODEBASE, EM_LIMITTEXT, MAX_URL_LENGTH - 1, 0);
|
|
SetFSPSCodebase(hdlg);
|
|
|
|
//InitFSPSType(hdlg);
|
|
SetFSPSType(hdlg);
|
|
|
|
SendDlgItemMessage(hdlg, IDD_ENTRYPOINT, EM_LIMITTEXT, MAX_PATH - 1, 0);
|
|
SetFSPSEntrypoint(hdlg);
|
|
|
|
SendDlgItemMessage(hdlg, IDD_START_IN, EM_LIMITTEXT, MAX_PATH - 1, 0);
|
|
SetFSPSWorkingDirectory(hdlg);
|
|
|
|
InitFSPSHotkey(hdlg);
|
|
|
|
InitFSPSShowCmds(hdlg);
|
|
SetFSPSShowCmd(hdlg);
|
|
}
|
|
else if (((PFSPS)(((PROPSHEETPAGE*)lparam)->lParam))->eCurPage == FUSIONSHCUT_PS_REF_PAGE)
|
|
{
|
|
// note: need limits on all editbox!
|
|
SetFSPSFriendlyName(hdlg);
|
|
SetFSPSName(hdlg);
|
|
SetFSPSVersion(hdlg);
|
|
SetFSPSCulture(hdlg);
|
|
SetFSPSPKT(hdlg);
|
|
}
|
|
// else do nothing?
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL FSPS_Destroy(HWND hdlg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
// FSPSCallback is called after this func. The remaining frees/releases are there
|
|
|
|
// wparam may be any value.
|
|
// lparam may be any value.
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
SetWindowLongPtr(hdlg, DWLP_USER, NULL);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
void FSPSChanged(HWND hdlg)
|
|
{
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
PropSheet_Changed(GetParent(hdlg), hdlg);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
HRESULT ChooseIcon(HWND hdlg)
|
|
{
|
|
HRESULT hr;
|
|
PFSPS pfsps;
|
|
CFusionShortcut* pfusshcut;
|
|
WCHAR rgchTempIconFile[MAX_PATH];
|
|
int niIcon;
|
|
UINT uFlags;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfsps = (PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
|
|
pfusshcut = pfsps->pfusshcut;
|
|
|
|
if (pfusshcut->GetIconLocation(0, rgchTempIconFile,
|
|
sizeof(rgchTempIconFile)/sizeof(WCHAR), &niIcon, &uFlags) != S_OK)
|
|
{
|
|
rgchTempIconFile[0] = '\0';
|
|
niIcon = 0;
|
|
}
|
|
|
|
ASSERT(wcslen(rgchTempIconFile) < (sizeof(rgchTempIconFile)/sizeof(WCHAR)));
|
|
|
|
// a private shell32.dll export (by ordinal)...
|
|
if (PickIconDlg(hdlg, rgchTempIconFile, sizeof(rgchTempIconFile)/sizeof(WCHAR), &niIcon)) //??? sizeof
|
|
{
|
|
ASSERT(wcslen(rgchTempIconFile) < (sizeof(pfsps->rgchIconFile)/sizeof(WCHAR)));
|
|
wcscpy(pfsps->rgchIconFile, rgchTempIconFile);
|
|
pfsps->niIcon = niIcon;
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
void UpdateFSPSIcon(HWND hdlg)
|
|
{
|
|
PFSPS pfsps;
|
|
HICON hicon;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfsps = (PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
|
|
ASSERT(pfsps->rgchIconFile[0]);
|
|
|
|
hicon = ExtractIcon(g_DllInstance, pfsps->rgchIconFile, pfsps->niIcon);
|
|
|
|
if (hicon)
|
|
SetFSPSIcon(hdlg, hicon);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL FSPS_Command(HWND hdlg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
BOOL bMsgHandled = FALSE;
|
|
WORD wCmd;
|
|
|
|
// wparam may be any value.
|
|
// lparam may be any value.
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
wCmd = HIWORD(wparam);
|
|
|
|
switch (LOWORD(wparam))
|
|
{
|
|
case IDD_CODEBASE:
|
|
case IDD_HOTKEY:
|
|
case IDD_ENTRYPOINT:
|
|
case IDD_START_IN:
|
|
case IDD_DISPLAY_NAME:
|
|
case IDD_NAME:
|
|
case IDD_VERSION:
|
|
case IDD_CULTURE:
|
|
case IDD_PKT:
|
|
case IDD_TYPE:
|
|
if (wCmd == EN_CHANGE)
|
|
{
|
|
FSPSChanged(hdlg);
|
|
|
|
bMsgHandled = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDD_SHOW_CMD:
|
|
if (wCmd == LBN_SELCHANGE)
|
|
{
|
|
FSPSChanged(hdlg);
|
|
|
|
bMsgHandled = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IDD_CHANGE_ICON:
|
|
// Ignore return value.
|
|
if (ChooseIcon(hdlg) == S_OK)
|
|
{
|
|
UpdateFSPSIcon(hdlg);
|
|
FSPSChanged(hdlg);
|
|
}
|
|
bMsgHandled = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return(bMsgHandled);
|
|
}
|
|
|
|
|
|
HRESULT InjectFSPSData(HWND hdlg)
|
|
{
|
|
// BUGBUG: TODO: this function should validate the user's changes...
|
|
|
|
HRESULT hr = S_OK;
|
|
PFSPS pfsps;
|
|
CFusionShortcut* pfusshcut;
|
|
LPWSTR pwzURL;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfsps = (PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
|
|
pfusshcut = pfsps->pfusshcut;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT FSPSSave(HWND hdlg)
|
|
{
|
|
HRESULT hr;
|
|
CFusionShortcut* pfusshcut;
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
|
|
|
|
if (pfusshcut->IsDirty() == S_OK)
|
|
{
|
|
// BUGBUG: TODO: IPersistFile::Save is not implemented
|
|
hr = pfusshcut->Save((LPCOLESTR)NULL, FALSE);
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
BOOL FSPS_Notify(HWND hdlg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
BOOL bMsgHandled = FALSE;
|
|
|
|
// wparam may be any value.
|
|
// lparam may be any value.
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
switch (((NMHDR*)lparam)->code)
|
|
{
|
|
case PSN_APPLY:
|
|
SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FSPSSave(hdlg) == S_OK ?
|
|
PSNRET_NOERROR :
|
|
PSNRET_INVALID_NOCHANGEPAGE);
|
|
bMsgHandled = TRUE;
|
|
break;
|
|
|
|
case PSN_KILLACTIVE:
|
|
SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FAILED(InjectFSPSData(hdlg)));
|
|
bMsgHandled = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return(bMsgHandled);
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK FSPS_DlgProc(HWND hdlg, UINT uMsg, WPARAM wparam,
|
|
LPARAM lparam)
|
|
{
|
|
INT_PTR bMsgHandled = FALSE;
|
|
|
|
// uMsg may be any value.
|
|
// wparam may be any value.
|
|
// lparam may be any value.
|
|
|
|
ASSERT(IS_VALID_HANDLE(hdlg, WND));
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
bMsgHandled = FSPS_InitDialog(hdlg, wparam, lparam);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
bMsgHandled = FSPS_Destroy(hdlg, wparam, lparam);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
bMsgHandled = FSPS_Command(hdlg, wparam, lparam);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
bMsgHandled = FSPS_Notify(hdlg, wparam, lparam);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return(bMsgHandled);
|
|
}
|
|
|
|
|
|
HRESULT AddFSPS(CFusionShortcut* pfusshcut,
|
|
LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lparam)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PFSPS pfsps;
|
|
PROPSHEETPAGE psp;
|
|
HPROPSHEETPAGE hpsp;
|
|
|
|
PFSPS pfsps2;
|
|
PROPSHEETPAGE psp2;
|
|
HPROPSHEETPAGE hpsp2;
|
|
|
|
// lparam may be any value.
|
|
|
|
// this is deleted in FSPSCallback
|
|
pfsps = new FSPS;
|
|
if (pfsps == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
ZeroMemory(pfsps, sizeof(*pfsps));
|
|
|
|
psp.dwSize = sizeof(psp);
|
|
psp.dwFlags = (PSP_DEFAULT | PSP_USECALLBACK);
|
|
psp.hInstance = g_DllInstance; //MLGetHinst();
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_FUS_SHORTCUT_PROP_SHEET);
|
|
psp.pfnDlgProc = &FSPS_DlgProc;
|
|
psp.pfnCallback = &FSPSCallback;
|
|
psp.lParam = (LPARAM)pfsps;
|
|
psp.hIcon = 0; // not used
|
|
psp.pszTitle = NULL; // not used
|
|
psp.pcRefParent = 0; // not used
|
|
|
|
pfsps->pfusshcut = pfusshcut;
|
|
pfsps->eCurPage = FUSIONSHCUT_PS_SHCUT_PAGE; // page 1
|
|
|
|
// will psp be copied in this func? else this won't work...!!??
|
|
hpsp = CreatePropertySheetPage(&psp);
|
|
|
|
if (hpsp)
|
|
{
|
|
if ((*pfnAddPage)(hpsp, lparam))
|
|
{
|
|
pfusshcut->AddRef();
|
|
}
|
|
else
|
|
{
|
|
DestroyPropertySheetPage(hpsp);
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// this is deleted in FSPSCallback
|
|
pfsps2 = new FSPS;
|
|
if (pfsps2 == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
ZeroMemory(pfsps2, sizeof(*pfsps2));
|
|
|
|
psp2.dwSize = sizeof(psp2);
|
|
psp2.dwFlags = (PSP_DEFAULT | PSP_USECALLBACK);
|
|
psp2.hInstance = g_DllInstance; //MLGetHinst();
|
|
psp2.pszTemplate = MAKEINTRESOURCE(DLG_FUS_SHORTCUT_PROP_SHEET_APPNAME);
|
|
psp2.pfnDlgProc = &FSPS_DlgProc;
|
|
psp2.pfnCallback = &FSPSCallback;
|
|
psp2.lParam = (LPARAM)pfsps2;
|
|
psp2.hIcon = 0; // not used
|
|
psp2.pszTitle = NULL; // not used
|
|
psp2.pcRefParent = 0; // not used
|
|
|
|
pfsps2->pfusshcut = pfusshcut;
|
|
pfsps2->eCurPage = FUSIONSHCUT_PS_REF_PAGE; // page 2
|
|
|
|
// will psp be copied in this func? else this won't work...!!??
|
|
hpsp2 = CreatePropertySheetPage(&psp2);
|
|
|
|
if (hpsp2)
|
|
{
|
|
if ((*pfnAddPage)(hpsp2, lparam))
|
|
{
|
|
pfusshcut->AddRef();
|
|
}
|
|
else
|
|
{
|
|
DestroyPropertySheetPage(hpsp2);
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
return(hr);
|
|
}
|
|
|
|
|
|
/****************************** Public Functions *****************************/
|
|
|
|
|
|
BOOL RegisterGlobalHotkey(WORD wOldHotkey, WORD wNewHotkey,
|
|
LPCWSTR pcwzPath)
|
|
{
|
|
// BUGBUG?: does this work??
|
|
|
|
BOOL bResult = FALSE;
|
|
HWND hwndTray;
|
|
|
|
ASSERT(! wOldHotkey || IsValidHotkey(wOldHotkey));
|
|
ASSERT(! wNewHotkey || IsValidHotkey(wNewHotkey));
|
|
ASSERT(IsValidPath(pcwzPath));
|
|
|
|
hwndTray = FindWindow(s_cwzTrayNotificationClass, 0);
|
|
|
|
if (hwndTray)
|
|
{
|
|
if (wOldHotkey)
|
|
{
|
|
SendMessage(hwndTray, WMTRAY_SCUNREGISTERHOTKEY, wOldHotkey, 0);
|
|
}
|
|
|
|
if (wNewHotkey)
|
|
{
|
|
ATOM atom = GlobalAddAtom(pcwzPath);
|
|
ASSERT(atom);
|
|
if (atom)
|
|
{
|
|
SendMessage(hwndTray, WMTRAY_SCREGISTERHOTKEY, wNewHotkey, (LPARAM)atom);
|
|
GlobalDeleteAtom(atom);
|
|
}
|
|
}
|
|
|
|
bResult = TRUE;
|
|
}
|
|
/*else
|
|
{
|
|
bResult = FALSE;
|
|
}*/
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
/********************************** Methods **********************************/
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CFusionShortcut::Initialize(LPCITEMIDLIST pcidlFolder,
|
|
IDataObject* pido,
|
|
HKEY hkeyProgID)
|
|
{
|
|
HRESULT hr;
|
|
STGMEDIUM stgmed;
|
|
FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
|
ASSERT(NULL != pido);
|
|
ASSERT(IS_VALID_HANDLE(hkeyProgID, KEY));
|
|
|
|
hr = pido->GetData(&fmtetc, &stgmed);
|
|
if (hr == S_OK)
|
|
{
|
|
WCHAR wzPath[MAX_PATH];
|
|
if (DragQueryFile((HDROP)stgmed.hGlobal, 0, wzPath, sizeof(wzPath)/sizeof(*wzPath)))
|
|
{
|
|
//mode is ignored for now
|
|
hr = Load(wzPath, 0);
|
|
}
|
|
// else path len > MAX_PATH or other error
|
|
|
|
ReleaseStgMedium(&stgmed);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CFusionShortcut::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage,
|
|
LPARAM lparam)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// lparam may be any value.
|
|
|
|
hr = AddFSPS(this, pfnAddPage, lparam);
|
|
|
|
// BUGBUG: why this does not work?
|
|
// From MSDN:
|
|
//With version 4.71 and later, you can request that a particular property
|
|
//sheet page be displayed first, instead of the default page. To do so,
|
|
//return the one-based index of the desired page. For example, if you
|
|
//want the second of three pages displayed, the return value should be 2.
|
|
//Note that this return value is a request. The property sheet may still
|
|
//display the default page. --> see doc for AddPages()
|
|
if (SUCCEEDED(hr))
|
|
hr = HRESULT(4); // or 3??
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CFusionShortcut::ReplacePage(UINT uPageID,
|
|
LPFNADDPROPSHEETPAGE pfnReplaceWith,
|
|
LPARAM lparam)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// lparam may be any value.
|
|
// uPageID may be any value.
|
|
|
|
hr = E_NOTIMPL;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CFusionShortcut::SetCodebase(LPCWSTR pcwzCodebase)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bDifferent;
|
|
LPWSTR pwzNewCodebase = NULL;
|
|
|
|
// Set m_pwzCodebase to codebase.
|
|
|
|
// check if empty string?
|
|
|
|
bDifferent = ! ((! pcwzCodebase && ! m_pwzCodebase) ||
|
|
(pcwzCodebase && m_pwzCodebase &&
|
|
! wcscmp(pcwzCodebase, m_pwzCodebase)));
|
|
|
|
if (bDifferent && pcwzCodebase)
|
|
{
|
|
// (+ 1) for null terminator.
|
|
|
|
pwzNewCodebase = new(WCHAR[wcslen(pcwzCodebase) + 1]);
|
|
|
|
if (pwzNewCodebase)
|
|
wcscpy(pwzNewCodebase, pcwzCodebase);
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (hr == S_OK && bDifferent)
|
|
{
|
|
if (m_pwzCodebase)
|
|
delete [] m_pwzCodebase;
|
|
|
|
m_pwzCodebase = pwzNewCodebase;
|
|
|
|
Dirty(TRUE);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CFusionShortcut::GetCodebase(LPWSTR pwzCodebase,
|
|
int ncBufLen)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get description from m_pwzCodebase.
|
|
|
|
if (m_pwzCodebase)
|
|
{
|
|
if (pwzCodebase == NULL || ncBufLen <= 0)
|
|
hr = E_INVALIDARG;
|
|
else
|
|
{
|
|
wcsncpy(pwzCodebase, m_pwzCodebase, ncBufLen-1);
|
|
pwzCodebase[ncBufLen-1] = L'\0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ncBufLen > 0 && pwzCodebase != NULL)
|
|
pwzCodebase = L'\0';
|
|
}
|
|
|
|
ASSERT(hr == S_OK &&
|
|
(ncBufLen <= 0 ||
|
|
EVAL(wcslen(pwzCodebase) < ncBufLen)));
|
|
|
|
return(hr);
|
|
}
|
|
|