2025-04-27 07:49:33 -04:00

1533 lines
30 KiB
C++

/*
* propsht.cpp - IPropSheetExt implementation for App Shortcut class.
*/
// * NOTE!!: this code is incomplete. Also error checking (any leak?),
// * restructuring (for better coding/efficiency) to be done.
// * this file uses CharNext etc as it needs User32 anyway *
/* Headers
**********/
#include "project.hpp"
#include <prsht.h>
#include "resource.h"
extern "C" WINSHELLAPI int WINAPI PickIconDlg(HWND hwnd, LPWSTR pwzIconPath, UINT cbIconPath, int *piIconIndex);
extern HINSTANCE g_DllInstance;
/* Types
********/
// Application Shortcut property sheet data
typedef enum _appshcutpropsheetpgs
{
APPSHCUT_PS_APPSHCUT_PAGE = 0x0000,
APPSHCUT_PS_APPREF_PAGE = 0x0001,
ALL_APPSHCUT_PS_PAGES
}
APPSHCUTPSPAGES;
typedef struct _asps
{
CAppShortcut* pappshcut;
WCHAR rgchIconFile[MAX_PATH];
int niIcon;
APPSHCUTPSPAGES eCurPage;
}
ASPS;
DECLARE_STANDARD_TYPES(ASPS);
typedef ASPS* PASPS;
/* 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
};
// this ordering has to match the strings in the resource file,
// the strings has to be in sync with the parsing code in persist.cpp
const int s_rgnType[] =
{
APPTYPE_NETASSEMBLY,
APPTYPE_WIN32EXE
};
/*
** 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 ASPSCallback(HWND hwnd, UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
// this is called after ASPS_DlgProc WM_DESTROY (ie. ASPS_Destroy)
// this func should do the frees/releases
UINT uResult = TRUE;
PASPS pasps = (PASPS)(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
pasps->pappshcut->Release();
// free the ASPS structure, this is created in AddASPS
// delete only after the ref is removed
delete pasps;
ppsp->lParam = NULL;
break;
default:
// ignore other msg - unhandled
break;
}
return(uResult);
}
void SetASPSIcon(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 SetASPSFileNameAndIcon(HWND hdlg)
{
HRESULT hr;
CAppShortcut* pappshcut;
WCHAR rgchFile[MAX_PATH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->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));
SetASPSIcon(hdlg, shfi.hIcon);
}
else
{
hr = E_FAIL;
}
}
if (hr != S_OK)
EVAL(SetDlgItemText(hdlg, IDD_NAME, g_cwzEmptyString));
return;
}
void SetASPSWorkingDirectory(HWND hdlg)
{
CAppShortcut* pappshcut;
HRESULT hr;
WCHAR rgchWorkingDirectory[MAX_PATH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->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 InitASPSHotkey(HWND hdlg)
{
CAppShortcut* pappshcut;
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.
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->GetHotkey(&wHotkey);
SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_SETHOTKEY, wHotkey, 0);
return;
}
void InitASPSShowCmds(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 SetASPSShowCmd(HWND hdlg)
{
CAppShortcut* pappshcut;
int nShowCmd;
int i;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
pappshcut->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 SetASPSDisplayName(HWND hdlg)
{
CAppShortcut* pappshcut;
HRESULT hr;
WCHAR rgchString[DISPLAYNAMESTRINGLENGTH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->GetDisplayName(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 SetASPSName(HWND hdlg)
{
CAppShortcut* pappshcut;
HRESULT hr;
WCHAR rgchString[NAMESTRINGLENGTH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->GetName(rgchString, sizeof(rgchString) / sizeof(WCHAR));
if (hr == S_OK)
{
EVAL(SetDlgItemText(hdlg, IDD_NAME, rgchString));
}
else
{
EVAL(SetDlgItemText(hdlg, IDD_NAME, g_cwzEmptyString));
}
return;
}
void SetASPSVersion(HWND hdlg)
{
CAppShortcut* pappshcut;
HRESULT hr;
WCHAR rgchString[VERSIONSTRINGLENGTH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->GetVersion(rgchString, sizeof(rgchString) / sizeof(WCHAR));
if (hr == S_OK)
{
EVAL(SetDlgItemText(hdlg, IDD_VERSION, rgchString));
}
else
{
EVAL(SetDlgItemText(hdlg, IDD_VERSION, g_cwzEmptyString));
}
return;
}
void SetASPSCulture(HWND hdlg)
{
CAppShortcut* pappshcut;
HRESULT hr;
WCHAR rgchString[CULTURESTRINGLENGTH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->GetCulture(rgchString, sizeof(rgchString) / sizeof(WCHAR));
if (hr == S_OK)
{
EVAL(SetDlgItemText(hdlg, IDD_CULTURE, rgchString));
}
else
{
EVAL(SetDlgItemText(hdlg, IDD_CULTURE, g_cwzEmptyString));
}
return;
}
void SetASPSPKT(HWND hdlg)
{
CAppShortcut* pappshcut;
HRESULT hr;
WCHAR rgchString[PKTSTRINGLENGTH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->GetPKT(rgchString, sizeof(rgchString) / sizeof(WCHAR));
if (hr == S_OK)
{
EVAL(SetDlgItemText(hdlg, IDD_PKT, rgchString));
}
else
{
EVAL(SetDlgItemText(hdlg, IDD_PKT, g_cwzEmptyString));
}
return;
}
void SetASPSCodebase(HWND hdlg)
{
CAppShortcut* pappshcut;
HRESULT hr;
WCHAR rgchString[MAX_URL_LENGTH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->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 SetASPSEntrypoint(HWND hdlg)
{
CAppShortcut* pappshcut;
HRESULT hr;
WCHAR rgchString[MAX_PATH];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
hr = pappshcut->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 InitASPSType(HWND hdlg)
{
int i;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
for (i = IDS_APPTYPE_NETASSEMBLY; i <= IDS_APPTYPE_WIN32EXE; i++)
{
WCHAR rgchString[s_ucMaxTypeLen];
if (LoadString(g_DllInstance, i, rgchString, s_ucMaxTypeLen))//sizeof(rgchShowCmd))) //MLLoadStringA
{
SendDlgItemMessage(hdlg, IDD_TYPE, CB_ADDSTRING, 0, (LPARAM)rgchString);
}
}
return;
}
void SetASPSType(HWND hdlg)
{
CAppShortcut* pappshcut;
int nType;
int i;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
pappshcut->GetAppType(&nType);
for (i = 0; i < ARRAY_ELEMENTS(s_rgnType); i++)
{
if (s_rgnType[i] == nType)
break;
}
if (i >= ARRAY_ELEMENTS(s_rgnType))
{
ASSERT(i == ARRAY_ELEMENTS(s_rgnType));
// not found! this clears the edit control - there's no default for this
// note: InjectASPSData has to handle this special case... as CB_ERR...
i = -1;
}
SendDlgItemMessage(hdlg, IDD_TYPE, CB_SETCURSEL, i, 0);
return;
}
BOOL ASPS_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 (((PASPS)(((PROPSHEETPAGE*)lparam)->lParam))->eCurPage == APPSHCUT_PS_APPSHCUT_PAGE)
{
SetASPSFileNameAndIcon(hdlg);
// note: need limits on all editbox!
SetASPSDisplayName(hdlg);
SendDlgItemMessage(hdlg, IDD_CODEBASE, EM_LIMITTEXT, MAX_URL_LENGTH - 1, 0);
SetASPSCodebase(hdlg);
InitASPSType(hdlg);
SetASPSType(hdlg);
SendDlgItemMessage(hdlg, IDD_ENTRYPOINT, EM_LIMITTEXT, MAX_PATH - 1, 0);
SetASPSEntrypoint(hdlg);
SendDlgItemMessage(hdlg, IDD_START_IN, EM_LIMITTEXT, MAX_PATH - 1, 0);
SetASPSWorkingDirectory(hdlg);
InitASPSHotkey(hdlg);
InitASPSShowCmds(hdlg);
SetASPSShowCmd(hdlg);
}
else if (((PASPS)(((PROPSHEETPAGE*)lparam)->lParam))->eCurPage == APPSHCUT_PS_APPREF_PAGE)
{
// note: need limits on all editbox!
SetASPSDisplayName(hdlg);
SetASPSName(hdlg);
SetASPSVersion(hdlg);
SetASPSCulture(hdlg);
SetASPSPKT(hdlg);
}
// else do nothing?
return(TRUE);
}
BOOL ASPS_Destroy(HWND hdlg, WPARAM wparam, LPARAM lparam)
{
// ASPSCallback 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 ASPSChanged(HWND hdlg)
{
ASSERT(IS_VALID_HANDLE(hdlg, WND));
PropSheet_Changed(GetParent(hdlg), hdlg);
return;
}
HRESULT ChooseIcon(HWND hdlg)
{
HRESULT hr;
PASPS pasps;
CAppShortcut* pappshcut;
WCHAR rgchTempIconFile[MAX_PATH];
int niIcon;
UINT uFlags;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pasps = (PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
pappshcut = pasps->pappshcut;
if (pappshcut->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), &niIcon)) //??? sizeof
{
ASSERT(wcslen(rgchTempIconFile) < (sizeof(pasps->rgchIconFile)/sizeof(WCHAR)));
wcscpy(pasps->rgchIconFile, rgchTempIconFile);
pasps->niIcon = niIcon;
hr = S_OK;
}
else
{
hr = E_FAIL;
}
return(hr);
}
void UpdateASPSIcon(HWND hdlg)
{
PASPS pasps;
HICON hicon;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pasps = (PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
ASSERT(pasps->rgchIconFile[0]);
hicon = ExtractIcon(g_DllInstance, pasps->rgchIconFile, pasps->niIcon);
if (hicon)
SetASPSIcon(hdlg, hicon);
return;
}
BOOL ASPS_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:
if (wCmd == EN_CHANGE)
{
ASPSChanged(hdlg);
bMsgHandled = TRUE;
}
break;
case IDD_SHOW_CMD:
case IDD_TYPE:
if (wCmd == LBN_SELCHANGE)
{
ASPSChanged(hdlg);
bMsgHandled = TRUE;
}
break;
case IDD_CHANGE_ICON:
// Ignore return value.
if (ChooseIcon(hdlg) == S_OK)
{
UpdateASPSIcon(hdlg);
ASPSChanged(hdlg);
}
bMsgHandled = TRUE;
break;
default:
break;
}
return(bMsgHandled);
}
HRESULT InjectASPSData(HWND hdlg)
{
// BUGBUG: TODO: this function should validate the user's changes...
HRESULT hr = S_OK;
PASPS pasps;
CAppShortcut* pappshcut;
LPWSTR pwzURL;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pasps = (PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
pappshcut = pasps->pappshcut;
return(hr);
}
HRESULT ASPSSave(HWND hdlg)
{
HRESULT hr;
CAppShortcut* pappshcut;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pappshcut = ((PASPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pappshcut;
if (pappshcut->IsDirty() == S_OK)
{
// BUGBUG: TODO: IPersistFile::Save is not implemented
hr = pappshcut->Save((LPCOLESTR)NULL, FALSE);
}
else
{
hr = S_OK;
}
return(hr);
}
BOOL ASPS_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, ASPSSave(hdlg) == S_OK ?
PSNRET_NOERROR :
PSNRET_INVALID_NOCHANGEPAGE);
bMsgHandled = TRUE;
break;
case PSN_KILLACTIVE:
SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FAILED(InjectASPSData(hdlg)));
bMsgHandled = TRUE;
break;
default:
break;
}
return(bMsgHandled);
}
INT_PTR CALLBACK ASPS_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 = ASPS_InitDialog(hdlg, wparam, lparam);
break;
case WM_DESTROY:
bMsgHandled = ASPS_Destroy(hdlg, wparam, lparam);
break;
case WM_COMMAND:
bMsgHandled = ASPS_Command(hdlg, wparam, lparam);
break;
case WM_NOTIFY:
bMsgHandled = ASPS_Notify(hdlg, wparam, lparam);
break;
default:
break;
}
return(bMsgHandled);
}
HRESULT AddASPS(CAppShortcut* pappshcut,
LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lparam)
{
HRESULT hr = S_OK;
PASPS pasps;
PROPSHEETPAGE psp;
HPROPSHEETPAGE hpsp;
PASPS pasps2;
PROPSHEETPAGE psp2;
HPROPSHEETPAGE hpsp2;
// lparam may be any value.
// this is deleted in ASPSCallback
pasps = new ASPS;
ZeroMemory(pasps, sizeof(*pasps));
psp.dwSize = sizeof(psp);
psp.dwFlags = (PSP_DEFAULT | PSP_USECALLBACK);
psp.hInstance = g_DllInstance; //MLGetHinst();
psp.pszTemplate = MAKEINTRESOURCE(DLG_APP_SHORTCUT_PROP_SHEET);
psp.pfnDlgProc = &ASPS_DlgProc;
psp.pfnCallback = &ASPSCallback;
psp.lParam = (LPARAM)pasps;
psp.hIcon = 0; // not used
psp.pszTitle = NULL; // not used
psp.pcRefParent = 0; // not used
pasps->pappshcut = pappshcut;
pasps->eCurPage = APPSHCUT_PS_APPSHCUT_PAGE; // page 1
// will psp be copied in this func? else this won't work...!!????????
hpsp = CreatePropertySheetPage(&psp);
if (hpsp)
{
if ((*pfnAddPage)(hpsp, lparam))
{
pappshcut->AddRef();
}
else
{
DestroyPropertySheetPage(hpsp);
hr = E_FAIL;
goto exit;
}
}
else
{
hr = E_OUTOFMEMORY;
goto exit;
}
// this is deleted in ASPSCallback
pasps2 = new ASPS;
ZeroMemory(pasps2, sizeof(*pasps2));
psp2.dwSize = sizeof(psp2);
psp2.dwFlags = (PSP_DEFAULT | PSP_USECALLBACK);
psp2.hInstance = g_DllInstance; //MLGetHinst();
psp2.pszTemplate = MAKEINTRESOURCE(DLG_APP_SHORTCUT_PROP_SHEET_APPNAME);
psp2.pfnDlgProc = &ASPS_DlgProc;
psp2.pfnCallback = &ASPSCallback;
psp2.lParam = (LPARAM)pasps2;
psp2.hIcon = 0; // not used
psp2.pszTitle = NULL; // not used
psp2.pcRefParent = 0; // not used
pasps2->pappshcut = pappshcut;
pasps2->eCurPage = APPSHCUT_PS_APPREF_PAGE; // page 2
// will psp be copied in this func? else this won't work...!!????????
hpsp2 = CreatePropertySheetPage(&psp2);
if (hpsp2)
{
if ((*pfnAddPage)(hpsp2, lparam))
{
pappshcut->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 CAppShortcut::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 CAppShortcut::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage,
LPARAM lparam)
{
HRESULT hr;
// lparam may be any value.
hr = AddASPS(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 CAppShortcut::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 CAppShortcut::SetDisplayName(LPCWSTR pcwzDisplayName)
{
// BUGBUG: not much checking is done!
BOOL bChanged = FALSE;
LPWSTR pwzOriString = NULL;
LPWSTR pwzNewString = (LPWSTR) pcwzDisplayName;
ASSERT(! pwzNewString);
if (!m_pappRefInfo)
return (E_FAIL);
pwzOriString = m_pappRefInfo->_wzDisplayName;
// ... this checks if all space in string...
if (! AnyNonWhiteSpace(pwzNewString))
pwzNewString = NULL;
bChanged = ! ((! pwzNewString && ! pwzOriString) ||
(pwzNewString && pwzOriString &&
! wcscmp(pwzNewString, pwzOriString)));
if (bChanged)
{
if (pwzNewString)
{
wcsncpy(pwzOriString, pwzNewString, DISPLAYNAMESTRINGLENGTH-1);
pwzOriString[DISPLAYNAMESTRINGLENGTH-1] = L'\0';
}
else
pwzOriString[0] = L'\0';
Dirty(TRUE);
}
return(S_OK);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::GetDisplayName(LPWSTR pwzDisplayName, int ncbLen)
{
HRESULT hr;
if (!m_pappRefInfo)
return (E_FAIL);
if (m_pappRefInfo->_wzDisplayName)
{
if ((int) wcslen(m_pappRefInfo->_wzDisplayName) < ncbLen)
{
wcsncpy(pwzDisplayName, m_pappRefInfo->_wzDisplayName, ncbLen-1);
pwzDisplayName[ncbLen-1] = L'\0';
hr = S_OK;
}
else
hr = E_FAIL;
}
else
{
if (ncbLen > 0)
pwzDisplayName = L'\0';
hr = S_FALSE;
}
return(hr);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::SetName(LPCWSTR pcwzName)
{
// BUGBUG: not much checking is done!
BOOL bChanged = FALSE;
LPWSTR pwzOriString = NULL;
LPWSTR pwzNewString = (LPWSTR) pcwzName;
ASSERT(! pwzNewString);
if (!m_pappRefInfo)
return (E_FAIL);
pwzOriString = m_pappRefInfo->_wzName;
// ... this checks if all space in string...
if (! AnyNonWhiteSpace(pwzNewString))
pwzNewString = NULL;
bChanged = ! ((! pwzNewString && ! pwzOriString) ||
(pwzNewString && pwzOriString &&
! wcscmp(pwzNewString, pwzOriString)));
if (bChanged)
{
if (pwzNewString)
{
wcsncpy(pwzOriString, pwzNewString, NAMESTRINGLENGTH-1);
pwzOriString[NAMESTRINGLENGTH-1] = L'\0';
}
else
pwzOriString[0] = L'\0';
Dirty(TRUE);
}
return(S_OK);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::GetName(LPWSTR pwzName, int ncbLen)
{
HRESULT hr;
if (!m_pappRefInfo)
return (E_FAIL);
if (m_pappRefInfo->_wzName)
{
if ((int) wcslen(m_pappRefInfo->_wzName) < ncbLen)
{
wcsncpy(pwzName, m_pappRefInfo->_wzName, ncbLen-1);
pwzName[ncbLen-1] = L'\0';
hr = S_OK;
}
else
hr = E_FAIL;
}
else
{
if (ncbLen > 0)
pwzName = L'\0';
hr = S_FALSE;
}
return(hr);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::SetVersion(LPCWSTR pcwzVersion)
{
// BUGBUG: not much checking is done!
BOOL bChanged = FALSE;
LPWSTR pwzOriString = NULL;
LPWSTR pwzNewString = (LPWSTR) pcwzVersion;
ASSERT(! pwzNewString);
if (!m_pappRefInfo)
return (E_FAIL);
pwzOriString = m_pappRefInfo->_wzVersion;
// ... this checks if all space in string...
if (! AnyNonWhiteSpace(pwzNewString))
pwzNewString = NULL;
bChanged = ! ((! pwzNewString && ! pwzOriString) ||
(pwzNewString && pwzOriString &&
! wcscmp(pwzNewString, pwzOriString)));
if (bChanged)
{
if (pwzNewString)
{
wcsncpy(pwzOriString, pwzNewString, VERSIONSTRINGLENGTH-1);
pwzOriString[VERSIONSTRINGLENGTH-1] = L'\0';
}
else
pwzOriString[0] = L'\0';
Dirty(TRUE);
}
return(S_OK);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::GetVersion(LPWSTR pwzVersion, int ncbLen)
{
HRESULT hr;
if (!m_pappRefInfo)
return (E_FAIL);
if (m_pappRefInfo->_wzVersion)
{
if ((int) wcslen(m_pappRefInfo->_wzVersion) < ncbLen)
{
wcsncpy(pwzVersion, m_pappRefInfo->_wzVersion, ncbLen-1);
pwzVersion[ncbLen-1] = L'\0';
hr = S_OK;
}
else
hr = E_FAIL;
}
else
{
if (ncbLen > 0)
pwzVersion = L'\0';
hr = S_FALSE;
}
return(hr);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::SetCulture(LPCWSTR pcwzCulture)
{
// BUGBUG: not much checking is done!
BOOL bChanged = FALSE;
LPWSTR pwzOriString = NULL;
LPWSTR pwzNewString = (LPWSTR) pcwzCulture;
ASSERT(! pwzNewString);
if (!m_pappRefInfo)
return (E_FAIL);
pwzOriString = m_pappRefInfo->_wzCulture;
// ... this checks if all space in string...
if (! AnyNonWhiteSpace(pwzNewString))
pwzNewString = NULL;
bChanged = ! ((! pwzNewString && ! pwzOriString) ||
(pwzNewString && pwzOriString &&
! wcscmp(pwzNewString, pwzOriString)));
if (bChanged)
{
if (pwzNewString)
{
wcsncpy(pwzOriString, pwzNewString, CULTURESTRINGLENGTH-1);
pwzOriString[CULTURESTRINGLENGTH-1] = L'\0';
}
else
pwzOriString[0] = L'\0';
Dirty(TRUE);
}
return(S_OK);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::GetCulture(LPWSTR pwzCulture, int ncbLen)
{
HRESULT hr;
if (!m_pappRefInfo)
return (E_FAIL);
if (m_pappRefInfo->_wzCulture)
{
if ((int) wcslen(m_pappRefInfo->_wzCulture) < ncbLen)
{
wcsncpy(pwzCulture, m_pappRefInfo->_wzCulture, ncbLen-1);
pwzCulture[ncbLen-1] = L'\0';
hr = S_OK;
}
else
hr = E_FAIL;
}
else
{
if (ncbLen > 0)
pwzCulture = L'\0';
hr = S_FALSE;
}
return(hr);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::SetPKT(LPCWSTR pcwzPKT)
{
// BUGBUG: not much checking is done!
BOOL bChanged = FALSE;
LPWSTR pwzOriString = NULL;
LPWSTR pwzNewString = (LPWSTR) pcwzPKT;
ASSERT(! pwzNewString);
if (!m_pappRefInfo)
return (E_FAIL);
pwzOriString = m_pappRefInfo->_wzPKT;
// ... this checks if all space in string...
if (! AnyNonWhiteSpace(pwzNewString))
pwzNewString = NULL;
bChanged = ! ((! pwzNewString && ! pwzOriString) ||
(pwzNewString && pwzOriString &&
! wcscmp(pwzNewString, pwzOriString)));
if (bChanged)
{
if (pwzNewString)
{
wcsncpy(pwzOriString, pwzNewString, PKTSTRINGLENGTH-1);
pwzOriString[PKTSTRINGLENGTH-1] = L'\0';
}
else
pwzOriString[0] = L'\0';
Dirty(TRUE);
}
return(S_OK);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::GetPKT(LPWSTR pwzPKT, int ncbLen)
{
HRESULT hr;
if (!m_pappRefInfo)
return (E_FAIL);
if (m_pappRefInfo->_wzPKT)
{
if ((int) wcslen(m_pappRefInfo->_wzPKT) < ncbLen)
{
wcsncpy(pwzPKT, m_pappRefInfo->_wzPKT, ncbLen-1);
pwzPKT[ncbLen-1] = L'\0';
hr = S_OK;
}
else
hr = E_FAIL;
}
else
{
if (ncbLen > 0)
pwzPKT = L'\0';
hr = S_FALSE;
}
return(hr);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::SetCodebase(LPCWSTR pcwzCodebase)
{
// BUGBUG: not much checking is done!
BOOL bChanged = FALSE;
LPWSTR pwzOriString = NULL;
LPWSTR pwzNewString = (LPWSTR) pcwzCodebase;
ASSERT(! pwzNewString);
if (!m_pappRefInfo)
return (E_FAIL);
pwzOriString = m_pappRefInfo->_wzCodebase;
// ... this checks if all space in string...
if (! AnyNonWhiteSpace(pwzNewString))
pwzNewString = NULL;
bChanged = ! ((! pwzNewString && ! pwzOriString) ||
(pwzNewString && pwzOriString &&
! wcscmp(pwzNewString, pwzOriString)));
if (bChanged)
{
if (pwzNewString)
{
wcsncpy(pwzOriString, pwzNewString, MAX_URL_LENGTH-1);
pwzOriString[MAX_URL_LENGTH-1] = L'\0';
}
else
pwzOriString[0] = L'\0';
Dirty(TRUE);
}
return(S_OK);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::GetCodebase(LPWSTR pwzCodebase, int ncbLen)
{
HRESULT hr;
if (!m_pappRefInfo)
return (E_FAIL);
if (m_pappRefInfo->_wzCodebase)
{
if ((int) wcslen(m_pappRefInfo->_wzCodebase) < ncbLen)
{
wcsncpy(pwzCodebase, m_pappRefInfo->_wzCodebase, ncbLen-1);
pwzCodebase[ncbLen-1] = L'\0';
hr = S_OK;
}
else
hr = E_FAIL;
}
else
{
if (ncbLen > 0)
pwzCodebase = L'\0';
hr = S_FALSE;
}
return(hr);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::SetAppType(int nAppType)
{
if (!m_pappRefInfo)
return (E_FAIL);
if (nAppType != m_pappRefInfo->_fAppType)
{
m_pappRefInfo->_fAppType = nAppType;
Dirty(TRUE);
}
return(S_OK);
}
HRESULT STDMETHODCALLTYPE CAppShortcut::GetAppType(PINT pnAppType)
{
if (!m_pappRefInfo)
return (E_FAIL);
*pnAppType = m_pappRefInfo->_fAppType;
return(S_OK);
}