/* * propsht.cpp - IPropSheetExt implementation for URL class. */ /* Headers **********/ #include "project.hpp" #pragma hdrstop #undef NO_HELP // for help.h #include #undef IDH_COMM_GROUPBOX // for addon.h #include #include "resource.h" #include /* 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 */