windows-nt/Source/XPSP1/NT/shell/ext/url/propsht.cpp

1428 lines
33 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*
* propsht.cpp - IPropSheetExt implementation for URL class.
*/
/* Headers
**********/
#include "project.hpp"
#pragma hdrstop
#undef NO_HELP // for help.h
#include <help.h>
#undef IDH_COMM_GROUPBOX // for addon.h
#include <addon.h>
#include "resource.h"
#include <mluisupp.h>
/* Types
********/
/* Internet Shortcut property sheet data */
typedef struct _isps
{
PROPSHEETPAGE psp;
PInternetShortcut pintshcut;
char rgchIconFile[MAX_PATH_LEN];
int niIcon;
}
ISPS;
DECLARE_STANDARD_TYPES(ISPS);
/* Module Constants
*******************/
#pragma data_seg(DATA_SEG_READ_ONLY)
// Tray notification window class
PRIVATE_DATA const char s_cszTrayNotificationClass[] = WNDCLASS_TRAYNOTIFY;
// HACKHACK: WMTRAY_SCREGISTERHOTKEY and WMTRAY_SCUNREGISTERHOTKEY are stolen
// from shelldll\link.c.
PRIVATE_DATA CUINT WMTRAY_SCREGISTERHOTKEY = (WM_USER + 233);
PRIVATE_DATA 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.
PRIVATE_DATA const UINT s_ucMaxShowCmdLen = MAX_PATH_LEN;
PRIVATE_DATA const int s_rgnShowCmds[] =
{
SW_SHOWNORMAL,
SW_SHOWMINNOACTIVE,
SW_SHOWMAXIMIZED
};
// help files
PRIVATE_DATA const char s_cszPlusHelpFile[] = "Plus!.hlp";
// help topics
PRIVATE_DATA const DWORD s_rgdwHelpIDs[] =
{
IDD_LINE_1, NO_HELP,
IDD_LINE_2, NO_HELP,
IDD_ICON, IDH_FCAB_LINK_ICON,
IDD_NAME, IDH_FCAB_LINK_NAME,
IDD_URL_TEXT, IDH_INTERNET_SHORTCUT_TARGET,
IDD_URL, IDH_INTERNET_SHORTCUT_TARGET,
IDD_HOTKEY_TEXT, IDH_FCAB_LINK_HOTKEY,
IDD_HOTKEY, IDH_FCAB_LINK_HOTKEY,
IDD_START_IN_TEXT, IDH_FCAB_LINK_WORKING,
IDD_START_IN, IDH_FCAB_LINK_WORKING,
IDD_SHOW_CMD, IDH_FCAB_LINK_RUN,
IDD_CHANGE_ICON, IDH_FCAB_LINK_CHANGEICON,
0, 0
};
#pragma data_seg()
/***************************** Private Functions *****************************/
#ifdef DEBUG
PRIVATE_CODE BOOL IsValidPCISPS(PCISPS pcisps)
{
return(IS_VALID_READ_PTR(pcisps, CISPS) &&
IS_VALID_STRUCT_PTR(&(pcisps->psp), CPROPSHEETPAGE) &&
IS_VALID_STRUCT_PTR(pcisps->pintshcut, CInternetShortcut) &&
EVAL(IsValidIconIndex(*(pcisps->rgchIconFile) ? S_OK : S_FALSE, pcisps->rgchIconFile, sizeof(pcisps->rgchIconFile), pcisps->niIcon)));
}
#endif
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE UINT CALLBACK ISPSCallback(HWND hwnd, UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
UINT uResult = TRUE;
PISPS pisps = (PISPS)ppsp;
// uMsg may be any value.
ASSERT(! hwnd ||
IS_VALID_HANDLE(hwnd, WND));
ASSERT(IS_VALID_STRUCT_PTR((PCISPS)ppsp, CISPS));
switch (uMsg)
{
case PSPCB_CREATE:
TRACE_OUT(("ISPSCallback(): Received PSPCB_CREATE."));
break;
case PSPCB_RELEASE:
TRACE_OUT(("ISPSCallback(): Received PSPCB_RELEASE."));
pisps->pintshcut->Release();
break;
default:
TRACE_OUT(("ISPSCallback(): Unhandled message %u.",
uMsg));
break;
}
return(uResult);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE void SetISPSIcon(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);
TRACE_OUT(("SetISPSIcon(): Set property sheet icon to %#lx.",
hicon));
return;
}
PRIVATE_CODE void SetISPSFileNameAndIcon(HWND hdlg)
{
HRESULT hr;
PInternetShortcut pintshcut;
char rgchFile[MAX_PATH_LEN];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
hr = pintshcut->GetCurFile(rgchFile, sizeof(rgchFile));
if (hr == S_OK)
{
SHFILEINFO shfi;
DWORD_PTR dwResult;
dwResult = SHGetFileInfo(rgchFile, 0, &shfi, sizeof(shfi),
(SHGFI_DISPLAYNAME | SHGFI_ICON));
if (dwResult)
{
PSTR pszFileName;
pszFileName = (PSTR)ExtractFileName(shfi.szDisplayName);
EVAL(SetDlgItemText(hdlg, IDD_NAME, pszFileName));
TRACE_OUT(("SetISPSFileNameAndIcon(): Set property sheet file name to \"%s\".",
pszFileName));
SetISPSIcon(hdlg, shfi.hIcon);
}
else
{
hr = E_FAIL;
TRACE_OUT(("SetISPSFileNameAndIcon(): SHGetFileInfo() failed, returning %lu.",
dwResult));
}
}
else
TRACE_OUT(("SetISPSFileNameAndIcon(): GetCurFile() failed, returning %s.",
GetHRESULTString(hr)));
if (hr != S_OK)
EVAL(SetDlgItemText(hdlg, IDD_NAME, EMPTY_STRING));
return;
}
PRIVATE_CODE void SetISPSURL(HWND hdlg)
{
PInternetShortcut pintshcut;
HRESULT hr;
PSTR pszURL;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
hr = pintshcut->GetURL(&pszURL);
if (hr == S_OK)
{
EVAL(SetDlgItemText(hdlg, IDD_URL, pszURL));
TRACE_OUT(("SetISPSURL(): Set property sheet URL to \"%s\".",
pszURL));
SHFree(pszURL);
pszURL = NULL;
}
else
EVAL(SetDlgItemText(hdlg, IDD_URL, EMPTY_STRING));
return;
}
PRIVATE_CODE void SetISPSWorkingDirectory(HWND hdlg)
{
PInternetShortcut pintshcut;
HRESULT hr;
char rgchWorkingDirectory[MAX_PATH_LEN];
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
hr = pintshcut->GetWorkingDirectory(rgchWorkingDirectory,
sizeof(rgchWorkingDirectory));
if (hr == S_OK)
{
EVAL(SetDlgItemText(hdlg, IDD_START_IN, rgchWorkingDirectory));
TRACE_OUT(("SetISPSWorkingDirectory(): Set property sheet working directory to \"%s\".",
rgchWorkingDirectory));
}
else
{
TRACE_OUT(("SetISPSWorkingDirectory(): GetWorkingDirectory() failed, returning %s.",
GetHRESULTString(hr)));
EVAL(SetDlgItemText(hdlg, IDD_START_IN, EMPTY_STRING));
}
return;
}
PRIVATE_CODE void InitISPSHotkey(HWND hdlg)
{
PInternetShortcut pintshcut;
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.
pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
hr = pintshcut->GetHotkey(&wHotkey);
SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_SETHOTKEY, wHotkey, 0);
return;
}
PRIVATE_CODE void InitISPSShowCmds(HWND hdlg)
{
int niShowCmd;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
for (niShowCmd = IDS_SHOW_NORMAL;
niShowCmd <= IDS_SHOW_MAXIMIZED;
niShowCmd++)
{
char rgchShowCmd[s_ucMaxShowCmdLen];
if (MLLoadStringA(niShowCmd, rgchShowCmd,
sizeof(rgchShowCmd)))
{
SendDlgItemMessage(hdlg, IDD_SHOW_CMD, CB_ADDSTRING, 0,
(LPARAM)rgchShowCmd);
TRACE_OUT(("InitISPSShowCmds(): Added show command \"%s\".",
rgchShowCmd));
}
else
ERROR_OUT(("InitISPSShowCmds(): Unable to load string %d.",
niShowCmd));
}
return;
}
PRIVATE_CODE void SetISPSShowCmd(HWND hdlg)
{
PInternetShortcut pintshcut;
int nShowCmd;
int i;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
pintshcut->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));
WARNING_OUT(("SetISPSShowCmd(): Unrecognized show command %d. Defaulting to normal.",
nShowCmd));
i = 0;
}
SendDlgItemMessage(hdlg, IDD_SHOW_CMD, CB_SETCURSEL, i, 0);
TRACE_OUT(("SetISPSShowCmd(): Set property sheet show command to index %d.",
i));
return;
}
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE BOOL ISPS_InitDialog(HWND hdlg, WPARAM wparam, LPARAM lparam)
{
PInternetShortcut pintshcut;
// wparam may be any value.
ASSERT(IS_VALID_HANDLE(hdlg, WND));
ASSERT(IS_VALID_STRUCT_PTR((PCISPS)lparam, CISPS));
SetWindowLongPtr(hdlg, DWLP_USER, lparam);
pintshcut = ((PISPS)lparam)->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
// Initialize control contents.
SetISPSFileNameAndIcon(hdlg);
SendDlgItemMessage(hdlg, IDD_URL, EM_LIMITTEXT, g_ucMaxURLLen - 1, 0);
SetISPSURL(hdlg);
SendDlgItemMessage(hdlg, IDD_START_IN, EM_LIMITTEXT, MAX_PATH_LEN - 1, 0);
SetISPSWorkingDirectory(hdlg);
InitISPSHotkey(hdlg);
InitISPSShowCmds(hdlg);
SetISPSShowCmd(hdlg);
return(TRUE);
}
PRIVATE_CODE BOOL ISPS_Destroy(HWND hdlg, WPARAM wparam, LPARAM lparam)
{
PInternetShortcut pintshcut;
// wparam may be any value.
// lparam may be any value.
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
SetWindowLongPtr(hdlg, DWLP_USER, NULL);
return(TRUE);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE void ISPSChanged(HWND hdlg)
{
ASSERT(IS_VALID_HANDLE(hdlg, WND));
PropSheet_Changed(GetParent(hdlg), hdlg);
return;
}
PRIVATE_CODE HRESULT ChooseIcon(HWND hdlg)
{
HRESULT hr;
PISPS pisps;
PInternetShortcut pintshcut;
char rgchTempIconFile[MAX_PATH_LEN];
int niIcon;
UINT uFlags;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pisps = (PISPS)GetWindowLongPtr(hdlg, DWLP_USER);
ASSERT(IS_VALID_STRUCT_PTR(pisps, CISPS));
pintshcut = pisps->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
if (pintshcut->GetIconLocation(0, rgchTempIconFile,
sizeof(rgchTempIconFile), &niIcon, &uFlags)
!= S_OK)
{
rgchTempIconFile[0] = '\0';
niIcon = 0;
}
ASSERT(lstrlen(rgchTempIconFile) < sizeof(rgchTempIconFile));
if (RUNNING_NT)
{
WCHAR uTempIconFile[MAX_PATH_LEN];
MultiByteToWideChar(CP_ACP, 0, rgchTempIconFile, -1,
uTempIconFile, MAX_PATH_LEN);
if (PickIconDlg(hdlg, uTempIconFile, MAX_PATH_LEN, &niIcon))
{
WideCharToMultiByte(CP_ACP, 0, uTempIconFile, -1, pisps->rgchIconFile,
MAX_PATH_LEN, NULL, NULL);
pisps->niIcon = niIcon;
hr = S_OK;
}
else
{
hr = E_FAIL;
TRACE_OUT(("ChooseIcon(NT): PickIconDlg() failed."));
}
}
else
{
if (PickIconDlg(hdlg, (LPWSTR)rgchTempIconFile, sizeof(rgchTempIconFile), &niIcon)) // (LPWSTR) so it builds, but works downlevel
{
ASSERT(lstrlen(rgchTempIconFile) < sizeof(pisps->rgchIconFile));
lstrcpy(pisps->rgchIconFile, rgchTempIconFile);
pisps->niIcon = niIcon;
hr = S_OK;
}
else
{
hr = E_FAIL;
TRACE_OUT(("ChooseIcon(): PickIconDlg() failed."));
}
}
return(hr);
}
PRIVATE_CODE void UpdateISPSIcon(HWND hdlg)
{
PISPS pisps;
HICON hicon;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pisps = (PISPS)GetWindowLongPtr(hdlg, DWLP_USER);
ASSERT(IS_VALID_STRUCT_PTR(pisps, CISPS));
ASSERT(pisps->rgchIconFile[0]);
// This icon does not have the link arrow overlayed. shell32.dll's
// Shortcut property sheet has the same bug.
hicon = ExtractIcon(GetThisModulesHandle(), pisps->rgchIconFile,
pisps->niIcon);
if (hicon)
SetISPSIcon(hdlg, hicon);
else
WARNING_OUT(("UpdateISPSIcon(): ExtractIcon() failed for icon %d in file %s.",
pisps->niIcon,
pisps->rgchIconFile));
return;
}
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE BOOL ISPS_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_URL:
case IDD_HOTKEY:
case IDD_START_IN:
if (wCmd == EN_CHANGE)
{
ISPSChanged(hdlg);
bMsgHandled = TRUE;
}
break;
case IDD_SHOW_CMD:
if (wCmd == LBN_SELCHANGE)
{
ISPSChanged(hdlg);
bMsgHandled = TRUE;
}
break;
case IDD_CHANGE_ICON:
// Ignore return value.
if (ChooseIcon(hdlg) == S_OK)
{
UpdateISPSIcon(hdlg);
ISPSChanged(hdlg);
}
bMsgHandled = TRUE;
break;
default:
break;
}
return(bMsgHandled);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE HRESULT ComplainAboutURL(HWND hwndParent, PCSTR pcszURL,
HRESULT hrError)
{
HRESULT hr;
int nResult;
// Validate hrError below.
ASSERT(IS_VALID_HANDLE(hwndParent, WND));
ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
switch (hrError)
{
case URL_E_UNREGISTERED_PROTOCOL:
{
PSTR pszProtocol;
hr = CopyURLProtocol(pcszURL, &pszProtocol);
if (hr == S_OK)
{
if (MyMsgBox(hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
MAKEINTRESOURCE(IDS_UNREGISTERED_PROTOCOL),
(MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION),
&nResult, pszProtocol))
{
switch (nResult)
{
case IDYES:
hr = S_OK;
TRACE_OUT(("ComplainAboutURL(): Allowing URL %s despite unregistered protocol %s, by request.",
pcszURL,
pszProtocol));
break;
default:
ASSERT(nResult == IDNO);
hr = E_FAIL;
TRACE_OUT(("ComplainAboutURL(): Not allowing URL %s because of unregistered protocol %s, as directed.",
pcszURL,
pszProtocol));
break;
}
}
delete pszProtocol;
pszProtocol = NULL;
}
break;
}
default:
ASSERT(hrError == URL_E_INVALID_SYNTAX);
if (MyMsgBox(hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
MAKEINTRESOURCE(IDS_INVALID_URL_SYNTAX),
(MB_OK | MB_ICONEXCLAMATION), &nResult, pcszURL)) {
ASSERT(nResult == IDOK);
}
hr = E_FAIL;
TRACE_OUT(("ComplainAboutURL(): Not allowing URL %s because of invalid syntax.",
pcszURL));
break;
}
return(hr);
}
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE HRESULT ComplainAboutWorkingDirectory(HWND hwndParent,
PCSTR pcszWorkingDirectory,
HRESULT hrError)
{
int nResult;
ASSERT(IS_VALID_HANDLE(hwndParent, WND));
ASSERT(IS_VALID_STRING_PTR(pcszWorkingDirectory, CSTR));
ASSERT(hrError == E_PATH_NOT_FOUND);
if (MyMsgBox(hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
MAKEINTRESOURCE(IDS_WORKING_DIR_NOT_FOUND),
(MB_OK | MB_ICONEXCLAMATION), &nResult, pcszWorkingDirectory)) {
ASSERT(nResult == IDOK);
}
TRACE_OUT(("ComplainAboutWorkingDirectory(): Not allowing non-existent working directory %s.",
pcszWorkingDirectory));
return(E_FAIL);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE HRESULT InjectISPSData(HWND hdlg)
{
HRESULT hr;
PISPS pisps;
PInternetShortcut pintshcut;
PSTR pszURL;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pisps = (PISPS)GetWindowLongPtr(hdlg, DWLP_USER);
ASSERT(IS_VALID_STRUCT_PTR(pisps, CISPS));
pintshcut = pisps->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
hr = CopyDlgItemText(hdlg, IDD_URL, &pszURL);
if (SUCCEEDED(hr))
{
PCSTR pcszURLToUse;
PSTR pszTranslatedURL;
pcszURLToUse = pszURL;
if (hr == S_OK)
{
hr = TranslateURL(pszURL, (TRANSLATEURL_FL_GUESS_PROTOCOL |
TRANSLATEURL_FL_USE_DEFAULT_PROTOCOL),
&pszTranslatedURL);
if (SUCCEEDED(hr))
{
if (hr == S_OK)
pcszURLToUse = pszTranslatedURL;
else
ASSERT(hr == S_FALSE);
hr = ValidateURL(pcszURLToUse);
if (FAILED(hr))
{
hr = ComplainAboutURL(hdlg, pcszURLToUse, hr);
if (FAILED(hr))
SetEditFocus(GetDlgItem(hdlg, IDD_URL));
}
}
}
else
{
// A blank URL is OK.
ASSERT(hr == S_FALSE);
pszTranslatedURL = NULL;
}
if (SUCCEEDED(hr))
{
hr = pintshcut->SetURL(pcszURLToUse, 0);
if (hr == S_OK)
{
WORD wHotkey;
WORD wOldHotkey;
// Refresh URL in case it was changed by TranslateURL().
SetISPSURL(hdlg);
wHotkey = (WORD)SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_GETHOTKEY,
0, 0);
hr = pintshcut->GetHotkey(&wOldHotkey);
if (hr == S_OK)
{
hr = pintshcut->SetHotkey(wHotkey);
if (hr == S_OK)
{
char szFile[MAX_PATH_LEN];
hr = pintshcut->GetCurFile(szFile, sizeof(szFile));
if (hr == S_OK)
{
if (RegisterGlobalHotkey(wOldHotkey, wHotkey, szFile))
{
PSTR pszWorkingDirectory;
hr = CopyDlgItemText(hdlg, IDD_START_IN,
&pszWorkingDirectory);
if (SUCCEEDED(hr))
{
if (hr == S_OK)
{
hr = ValidateWorkingDirectory(pszWorkingDirectory);
if (FAILED(hr))
hr = ComplainAboutWorkingDirectory(hdlg,
pszWorkingDirectory,
hr);
if (FAILED(hr))
SetEditFocus(GetDlgItem(hdlg, IDD_START_IN));
}
if (SUCCEEDED(hr))
{
hr = pintshcut->SetWorkingDirectory(pszWorkingDirectory);
if (hr == S_OK)
{
// Refresh working directory in case it was changed by
// SetWorkingDirectory().
SetISPSWorkingDirectory(hdlg);
if (pisps->rgchIconFile[0])
hr = pintshcut->SetIconLocation(pisps->rgchIconFile,
pisps->niIcon);
if (hr == S_OK)
{
INT_PTR iShowCmd;
iShowCmd = SendDlgItemMessage(hdlg,
IDD_SHOW_CMD,
CB_GETCURSEL,
0, 0);
if (iShowCmd >= 0 &&
iShowCmd < ARRAY_ELEMENTS(s_rgnShowCmds))
pintshcut->SetShowCmd(s_rgnShowCmds[iShowCmd]);
else
hr = E_UNEXPECTED;
}
}
}
if (pszWorkingDirectory)
{
delete pszWorkingDirectory;
pszWorkingDirectory = NULL;
}
}
}
else
hr = E_FAIL;
}
}
}
}
}
if (pszURL)
{
delete pszURL;
pszURL = NULL;
}
if (pszTranslatedURL)
{
LocalFree(pszTranslatedURL);
pszTranslatedURL = NULL;
}
}
if (hr == S_OK)
TRACE_OUT(("InjectISPSData(): Injected property sheet data into Internet Shortcut successfully."));
else
WARNING_OUT(("InjectISPSData(): Failed to inject property sheet data into Internet Shortcut, returning %s.",
GetHRESULTString(hr)));
return(hr);
}
PRIVATE_CODE HRESULT ISPSSave(HWND hdlg)
{
HRESULT hr;
PInternetShortcut pintshcut;
ASSERT(IS_VALID_HANDLE(hdlg, WND));
pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
if (pintshcut->IsDirty() == S_OK)
{
hr = pintshcut->Save((LPCOLESTR)NULL, FALSE);
if (hr == S_OK)
TRACE_OUT(("ISPSSave(): Saved Internet Shortcut successfully."));
else
WARNING_OUT(("ISPSSave(): Save() failed, returning %s.",
GetHRESULTString(hr)));
}
else
{
TRACE_OUT(("ISPSSave(): Internet Shortcut unchanged. No save required."));
hr = S_OK;
}
return(hr);
}
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE BOOL ISPS_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 (((PNMHDR)lparam)->code)
{
case PSN_APPLY:
SetWindowLongPtr(hdlg, DWLP_MSGRESULT, ISPSSave(hdlg) == S_OK ?
PSNRET_NOERROR :
PSNRET_INVALID_NOCHANGEPAGE);
bMsgHandled = TRUE;
break;
case PSN_KILLACTIVE:
SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FAILED(InjectISPSData(hdlg)));
bMsgHandled = TRUE;
break;
default:
break;
}
return(bMsgHandled);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
PRIVATE_CODE PCSTR ISPS_GetHelpFileFromControl(HWND hwndControl)
{
PCSTR pcszHelpFile = NULL;
int nControlID = 0;
ASSERT(! hwndControl ||
IS_VALID_HANDLE(hwndControl, WND));
if (hwndControl)
{
nControlID = GetDlgCtrlID(hwndControl);
switch (nControlID)
{
case IDD_URL_TEXT:
case IDD_URL:
// URL help comes from the Plus! Pack help file.
pcszHelpFile = s_cszPlusHelpFile;
break;
default:
// Other help is borrowed from the default Win95 help file.
break;
}
}
TRACE_OUT(("ISPS_GetHelpFileFromControl(): Using %s for control %d (HWND %#lx).",
pcszHelpFile ? pcszHelpFile : "default Win95 help file",
nControlID,
hwndControl));
ASSERT(! pcszHelpFile ||
IS_VALID_STRING_PTR(pcszHelpFile, CSTR));
return(pcszHelpFile);
}
PRIVATE_CODE INT_PTR CALLBACK ISPS_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 = ISPS_InitDialog(hdlg, wparam, lparam);
break;
case WM_DESTROY:
bMsgHandled = ISPS_Destroy(hdlg, wparam, lparam);
break;
case WM_COMMAND:
bMsgHandled = ISPS_Command(hdlg, wparam, lparam);
break;
case WM_NOTIFY:
bMsgHandled = ISPS_Notify(hdlg, wparam, lparam);
break;
case WM_HELP:
SHWinHelpOnDemandWrap((HWND)(((LPHELPINFO)lparam)->hItemHandle),
ISPS_GetHelpFileFromControl((HWND)(((LPHELPINFO)lparam)->hItemHandle)),
HELP_WM_HELP, (DWORD_PTR)(PVOID)s_rgdwHelpIDs);
bMsgHandled = TRUE;
break;
case WM_CONTEXTMENU:
{
POINT pt;
LPARAM_TO_POINT(lparam, pt);
EVAL(ScreenToClient(hdlg, &pt));
SHWinHelpOnDemandWrap((HWND)wparam,
ISPS_GetHelpFileFromControl(ChildWindowFromPoint(hdlg, pt)),
HELP_CONTEXTMENU, (DWORD_PTR)(PVOID)s_rgdwHelpIDs);
bMsgHandled = TRUE;
break;
}
default:
break;
}
return(bMsgHandled);
}
PRIVATE_CODE HRESULT AddISPS(PInternetShortcut pintshcut,
LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lparam)
{
HRESULT hr;
ISPS isps;
HPROPSHEETPAGE hpsp;
// lparam may be any value.
ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
ASSERT(IS_VALID_CODE_PTR(pfnAddPage, LPFNADDPROPSHEETPAGE));
ZeroMemory(&isps, sizeof(isps));
isps.psp.dwSize = sizeof(isps);
isps.psp.dwFlags = (PSP_DEFAULT | PSP_USECALLBACK);
isps.psp.hInstance = MLGetHinst();
isps.psp.pszTemplate = MAKEINTRESOURCE(DLG_INTERNET_SHORTCUT_PROP_SHEET);
isps.psp.pfnDlgProc = &ISPS_DlgProc;
isps.psp.pfnCallback = &ISPSCallback;
isps.pintshcut = pintshcut;
ASSERT(IS_VALID_STRUCT_PTR(&isps, CISPS));
hpsp = CreatePropertySheetPage(&(isps.psp));
if (hpsp)
{
if ((*pfnAddPage)(hpsp, lparam))
{
pintshcut->AddRef();
hr = S_OK;
TRACE_OUT(("AddISPS(): Added Internet Shortcut property sheet."));
}
else
{
DestroyPropertySheetPage(hpsp);
hr = E_FAIL;
WARNING_OUT(("AddISPS(): Callback to add property sheet failed."));
}
}
else
hr = E_OUTOFMEMORY;
return(hr);
}
/****************************** Public Functions *****************************/
PUBLIC_CODE void SetEditFocus(HWND hwnd)
{
ASSERT(IS_VALID_HANDLE(hwnd, WND));
SetFocus(hwnd);
SendMessage(hwnd, EM_SETSEL, 0, -1);
return;
}
PUBLIC_CODE BOOL ConstructMessageString(PCSTR pcszFormat, PSTR *ppszMsg,
va_list *ArgList)
{
BOOL bResult;
char rgchFormat[MAX_MSG_LEN];
// ArgList may be any value.
ASSERT(! HIWORD(pcszFormat) ||
IS_VALID_STRING_PTR(pcszFormat, CSTR));
ASSERT(IS_VALID_WRITE_PTR(ppszMsg, PSTR));
if (IS_INTRESOURCE(pcszFormat))
{
MLLoadStringA(LOWORD(PtrToUlong(pcszFormat)), rgchFormat,
sizeof(rgchFormat));
pcszFormat = rgchFormat;
}
bResult = FormatMessage((FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_STRING), pcszFormat, 0, 0,
(PSTR)ppszMsg, 0, ArgList);
ASSERT(! bResult ||
IS_VALID_STRING_PTR(*ppszMsg, STR));
return(bResult);
}
PUBLIC_CODE BOOL __cdecl MyMsgBox(HWND hwndParent, PCSTR pcszTitle,
PCSTR pcszMsgFormat, DWORD dwMsgBoxFlags,
PINT pnResult, ...)
{
BOOL bResult;
va_list ArgList;
PSTR pszMsg;
ASSERT(IS_VALID_HANDLE(hwndParent, WND));
ASSERT(IS_INTRESOURCE(pcszTitle) ||
IS_VALID_STRING_PTR(pcszTitle, CSTR));
ASSERT(IS_INTRESOURCE(pcszMsgFormat) ||
IS_VALID_STRING_PTR(pcszMsgFormat, CSTR));
ASSERT(FLAGS_ARE_VALID(dwMsgBoxFlags, ALL_MSG_BOX_FLAGS));
ASSERT(IS_VALID_WRITE_PTR(pnResult, INT));
*pnResult = 0;
va_start(ArgList, pnResult);
bResult = ConstructMessageString(pcszMsgFormat, &pszMsg, &ArgList);
va_end(ArgList);
if (bResult)
{
char rgchTitle[MAX_MSG_LEN];
if (! HIWORD(pcszTitle))
{
MLLoadStringA(LOWORD(PtrToUlong(pcszTitle)), rgchTitle,
sizeof(rgchTitle));
pcszTitle = rgchTitle;
}
*pnResult = MessageBox(hwndParent, pszMsg, pcszTitle, dwMsgBoxFlags);
bResult = (*pnResult != 0);
LocalFree(pszMsg);
pszMsg = NULL;
}
return(bResult);
}
PUBLIC_CODE HRESULT CopyDlgItemText(HWND hdlg, int nControlID, PSTR *ppszText)
{
HRESULT hr;
HWND hwndControl;
// nContolID may be any value.
ASSERT(IS_VALID_HANDLE(hdlg, WND));
ASSERT(IS_VALID_WRITE_PTR(ppszText, PSTR));
*ppszText = NULL;
hwndControl = GetDlgItem(hdlg, nControlID);
if (hwndControl)
{
int ncchTextLen;
ncchTextLen = GetWindowTextLength(hwndControl);
if (ncchTextLen > 0)
{
PSTR pszText;
ASSERT(ncchTextLen < INT_MAX);
ncchTextLen++;
ASSERT(ncchTextLen > 0);
pszText = new(char[ncchTextLen]);
if (pszText)
{
int ncchCopiedLen;
ncchCopiedLen = GetWindowText(hwndControl, pszText, ncchTextLen);
ASSERT(ncchCopiedLen == ncchTextLen - 1);
if (EVAL(ncchCopiedLen > 0))
{
if (AnyMeat(pszText))
{
*ppszText = pszText;
hr = S_OK;
}
else
hr = S_FALSE;
}
else
hr = E_FAIL;
if (hr != S_OK)
{
delete pszText;
pszText = NULL;
}
}
else
hr = E_OUTOFMEMORY;
}
else
// No text.
hr = S_FALSE;
}
else
hr = E_FAIL;
return(hr);
}
PUBLIC_CODE BOOL RegisterGlobalHotkey(WORD wOldHotkey, WORD wNewHotkey,
PCSTR pcszPath)
{
BOOL bResult;
HWND hwndTray;
ASSERT(! wOldHotkey ||
IsValidHotkey(wOldHotkey));
ASSERT(! wNewHotkey ||
IsValidHotkey(wNewHotkey));
ASSERT(IsValidPath(pcszPath));
hwndTray = FindWindow(s_cszTrayNotificationClass, 0);
if (hwndTray)
{
if (wOldHotkey)
{
SendMessage(hwndTray, WMTRAY_SCUNREGISTERHOTKEY, wOldHotkey, 0);
TRACE_OUT(("RegisterGlobalHotkey(): Unregistered old hotkey %#04x for %s.",
wOldHotkey,
pcszPath));
}
if (wNewHotkey)
{
if (RUNNING_NT)
{
ATOM atom = GlobalAddAtom(pcszPath);
ASSERT(atom);
if (atom)
{
SendMessage(hwndTray, WMTRAY_SCREGISTERHOTKEY, wNewHotkey, (LPARAM)atom);
GlobalDeleteAtom(atom);
}
}
else
{
SendMessage(hwndTray, WMTRAY_SCREGISTERHOTKEY, wNewHotkey,
(LPARAM)pcszPath);
}
TRACE_OUT(("RegisterGlobalHotkey(): Registered new hotkey %#04x for %s.",
wNewHotkey,
pcszPath));
}
bResult = TRUE;
}
else
{
bResult = FALSE;
WARNING_OUT(("RegisterGlobalHotkey(): Unable to find Tray window of class %s to notify.",
s_cszTrayNotificationClass));
}
return(bResult);
}
/********************************** Methods **********************************/
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
HRESULT STDMETHODCALLTYPE InternetShortcut::Initialize(
PCITEMIDLIST pcidlFolder,
PIDataObject pido,
HKEY hkeyProgID)
{
HRESULT hr;
FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stgmed;
DebugEntry(InternetShortcut::Initialize);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
ASSERT(! pcidlFolder ||
IS_VALID_STRUCT_PTR(pcidlFolder, CITEMIDLIST));
ASSERT(IS_VALID_INTERFACE_PTR(pido, IDataObject));
ASSERT(IS_VALID_HANDLE(hkeyProgID, KEY));
hr = pido->GetData(&fmtetc, &stgmed);
if (hr == S_OK)
{
UINT ucbPathLen;
PSTR pszFile;
// (+ 1) for null terminator.
ucbPathLen = DragQueryFile((HDROP)(stgmed.hGlobal), 0, NULL, 0) + 1;
ASSERT(ucbPathLen > 0);
pszFile = new(char[ucbPathLen]);
if (pszFile)
{
EVAL(DragQueryFile((HDROP)(stgmed.hGlobal), 0, pszFile, ucbPathLen) == ucbPathLen - 1);
ASSERT(IS_VALID_STRING_PTR(pszFile, STR));
ASSERT((UINT)lstrlen(pszFile) == ucbPathLen - 1);
hr = LoadFromFile(pszFile, TRUE);
delete pszFile;
pszFile = NULL;
}
else
hr = E_OUTOFMEMORY;
if (stgmed.tymed != TYMED_NULL)
MyReleaseStgMedium(&stgmed);
}
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::Initialize, hr);
return(hr);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */
HRESULT STDMETHODCALLTYPE InternetShortcut::AddPages(
LPFNADDPROPSHEETPAGE pfnAddPage,
LPARAM lparam)
{
HRESULT hr;
DebugEntry(InternetShortcut::AddPages);
// lparam may be any value.
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
ASSERT(IS_VALID_CODE_PTR(pfnAddPage, LPFNADDPROPSHEETPAGE));
hr = AddISPS(this, pfnAddPage, lparam);
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::AddPages, hr);
return(hr);
}
#pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
HRESULT STDMETHODCALLTYPE InternetShortcut::ReplacePage(
UINT uPageID,
LPFNADDPROPSHEETPAGE pfnReplaceWith,
LPARAM lparam)
{
HRESULT hr;
DebugEntry(InternetShortcut::ReplacePage);
// lparam may be any value.
// uPageID may be any value.
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
ASSERT(IS_VALID_CODE_PTR(pfnReplaceWith, LPFNADDPROPSHEETPAGE));
hr = E_NOTIMPL;
ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
DebugExitHRESULT(InternetShortcut::ReplacePage, hr);
return(hr);
}
#pragma warning(default:4100) /* "unreferenced formal parameter" warning */