Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
link.c
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 38k
Category:
Windows Kernel
Development Platform:
Visual C++
- //---------------------------------------------------------------------------
- //
- // link.c linke property page implementation
- //
- //---------------------------------------------------------------------------
- #include "shellprv.h"
- #pragma hdrstop
- #include "fstreex.h"
- #include "docfind.h"
- #include "lnkcon.h"
- #include "trayp.h" // for WMTRAY_ messages
- #include "util.h" // for GetIconLocationFromExt
- #define LNKM_ACTIVATEOTHER (WM_USER + 100) // don't conflict with DM_ messages
- //
- // This string defined in shlink.c - hack to allow user to set working dir to $$
- // and have it map to whatever "My Documents" is mapped to.
- //
- void _UpdateLinkIcon(LPLINKPROP_DATA plpd, HICON hIcon)
- {
- if (!hIcon)
- hIcon = SHGetFileIcon(NULL, plpd->szFile, 0, SHGFI_LARGEICON);
- if (hIcon)
- {
- HICON hOldIcon = (HICON)SendDlgItemMessage(plpd->hDlg, IDD_ITEMICON, STM_SETICON, (WPARAM)hIcon, 0L);
- if (hOldIcon)
- DestroyIcon(hOldIcon);
- }
- }
- // make sure LFN paths are nicly quoted and have args at the end
- void PathComposeWithArgs(LPTSTR pszPath, LPTSTR pszArgs)
- {
- PathQuoteSpaces(pszPath);
- if (pszArgs[0])
- {
- int len = lstrlen(pszPath);
- if (len < (MAX_PATH - 3))
- { // 1 for null, 1 for space, 1 for arg
- pszPath[len++] = TEXT(' ');
- lstrcpyn(pszPath + len, pszArgs, MAX_PATH - len);
- }
- }
- }
- // do the inverse of the above, parse pszPath into a unquoted
- // path string and put the args in pszArgs
- //
- // returns:
- // TRUE we verified the thing exists
- // FALSE it may not exist
- BOOL PathSeperateArgs(LPTSTR pszPath, LPTSTR pszArgs)
- {
- LPTSTR pszT;
- PathRemoveBlanks(pszPath);
- // if the unquoted sting exists as a file just use it
- if (PathFileExistsAndAttributes(pszPath, NULL))
- {
- *pszArgs = 0;
- return TRUE;
- }
- pszT = PathGetArgs(pszPath);
- if (*pszT)
- *(pszT - 1) = 0;
- lstrcpy(pszArgs, pszT);
- PathUnquoteSpaces(pszPath);
- return FALSE;
- }
- // put a path into an edit field, doing quoting as necessary
- void SetDlgItemPath(HWND hdlg, int id, LPTSTR pszPath)
- {
- PathQuoteSpaces(pszPath);
- SetDlgItemText(hdlg, id, pszPath);
- }
- // get a path from an edit field, unquoting as possible
- void GetDlgItemPath(HWND hdlg, int id, LPTSTR pszPath)
- {
- GetDlgItemText(hdlg, id, pszPath, MAX_PATH);
- PathRemoveBlanks(pszPath);
- PathUnquoteSpaces(pszPath);
- }
- const int c_iShowCmds[] = {
- SW_SHOWNORMAL,
- SW_SHOWMINNOACTIVE,
- SW_SHOWMAXIMIZED,
- };
- void _DisableAllChildren(HWND hwnd)
- {
- HWND hwndChild;
- for (hwndChild = GetWindow(hwnd, GW_CHILD); hwndChild != NULL; hwndChild = GetWindow(hwndChild, GW_HWNDNEXT))
- {
- // we don't want to disable the static text controls (makes the dlg look bad)
- if (!(SendMessage(hwndChild, WM_GETDLGCODE, 0, 0) & DLGC_STATIC))
- {
- EnableWindow(hwndChild, FALSE);
- }
- }
- }
- void _GetPathAndArgs(LPLINKPROP_DATA plpd, LPTSTR pszPath, LPTSTR pszArgs)
- {
- GetDlgItemText(plpd->hDlg, IDD_FILENAME, pszPath, MAX_PATH);
- PathSeperateArgs(pszPath, pszArgs);
- }
- #ifdef WINNT
- //
- // Returns fully qualified path to target of link, and # of characters
- // in fully qualifed path as return value
- //
- INT _GetTargetOfLink(LPLINKPROP_DATA plpd, LPTSTR pszTarget )
- {
- TCHAR szFile[MAX_PATH], szArgs[MAX_PATH];
- INT cch = 0;
- *pszTarget = 0;
- _GetPathAndArgs(plpd, szFile, szArgs);
- if (szFile[0])
- {
- LPTSTR psz;
- TCHAR szExp[MAX_PATH];
- if (SHExpandEnvironmentStrings(szFile, szExp, ARRAYSIZE(szExp)))
- {
- cch = SearchPath(NULL, szExp, TEXT(".EXE"), MAX_PATH, pszTarget, &psz);
- }
- }
- return cch;
- }
- //
- // Do checking of the .exe type in the background so the UI doesn't
- // get hung up while we scan. This is particularly important with
- // the .exe is over the network or on a floppy.
- //
- STDAPI_(DWORD) _LinkCheckThreadProc(void *pv)
- {
- LINKPROP_DATA *plpd = (LINKPROP_DATA *)pv;
- BOOL fCheck = TRUE, fEnable = FALSE;
- DebugMsg(DM_TRACE, TEXT("_LinkCheckThreadProc created and running"));
- while (plpd->bCheckRunInSep)
- {
- WaitForSingleObject( plpd->hCheckNow, INFINITE);
- ResetEvent(plpd->hCheckNow);
- if (plpd->bCheckRunInSep)
- {
- TCHAR szFullFile[MAX_PATH];
- DWORD cch = _GetTargetOfLink(plpd, szFullFile);
- if ((cch != 0) && (cch < ARRAYSIZE(szFullFile)))
- {
- LONG lBinaryType;
- if (PathIsUNC( szFullFile ) || IsRemoteDrive(DRIVEID(szFullFile)))
- {
- // Net Path, let the user decide...
- fCheck = FALSE;
- fEnable = TRUE;
- }
- else if (GetBinaryType( szFullFile, &lBinaryType) && (lBinaryType==SCS_WOW_BINARY))
- {
- // 16-bit binary, let the user decide, default to same VDM
- fCheck = FALSE;
- fEnable = TRUE;
- }
- else
- {
- // 32-bit binary, or non-net path. don't enable the control
- fCheck = TRUE;
- fEnable = FALSE;
- }
- }
- else
- {
- // Error getting target of the link. don't enable the control
- fCheck = TRUE;
- fEnable = FALSE;
- }
- CheckDlgButton(plpd->hDlg, IDD_RUNINSEPARATE, fCheck ? 1 : 0);
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_RUNINSEPARATE), fEnable);
- }
- }
- CloseHandle(plpd->hCheckNow);
- DebugMsg(DM_TRACE, TEXT("_LinkCheckThreadProc exiting now..."));
- return 0;
- }
- // shut down the thread
- void _StopThread(LINKPROP_DATA *plpd)
- {
- if (plpd->hThread)
- {
- plpd->bCheckRunInSep = FALSE;
- SetEvent(plpd->hCheckNow);
- if (WaitForSingleObject(plpd->hThread, 2000) == WAIT_TIMEOUT)
- TerminateThread(plpd->hThread, (DWORD)-1); // Blow it away!
- CloseHandle(plpd->hThread);
- plpd->hThread = NULL;
- }
- }
- #endif // WINNT
- LPVOID _GetLinkExtraData(IShellLink* psl, DWORD dwSig)
- {
- LPVOID pDataBlock = NULL;
- IShellLinkDataList *psld;
- if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl, &IID_IShellLinkDataList, (void **)&psld)))
- {
- psld->lpVtbl->CopyDataBlock(psld, dwSig, &pDataBlock);
- psld->lpVtbl->Release(psld);
- }
- return pDataBlock;
- }
- DWORD _GetLinkFlags(IShellLink *psl)
- {
- DWORD dw = 0;
- IShellLinkDataList *psld;
- if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl, &IID_IShellLinkDataList, (void **)&psld)))
- {
- psld->lpVtbl->GetFlags(psld, &dw);
- psld->lpVtbl->Release(psld);
- }
- return dw;
- }
- void _SetLinkFlags(IShellLink *psl, DWORD dwFlags)
- {
- IShellLinkDataList *psld;
- if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl, &IID_IShellLinkDataList, (void **)&psld)))
- {
- psld->lpVtbl->SetFlags(psld, dwFlags);
- psld->lpVtbl->Release(psld);
- }
- }
- // Initializes the generic link dialog box.
- void _UpdateLinkDlg(LPLINKPROP_DATA plpd, BOOL bUpdatePath)
- {
- WORD wHotkey;
- int i, iShowCmd;
- TCHAR szBuffer[MAX_PATH];
- TCHAR szCommand[MAX_PATH];
- HRESULT hres;
- SHFILEINFO sfi;
- BOOL fIsDarwinLink = _GetLinkFlags(plpd->psl) & SLDF_HAS_DARWINID;
- // do this here so we don't slow down the loading
- // of other pages
- if (!bUpdatePath)
- {
- IPersistFile *ppf;
- if (SUCCEEDED(plpd->psl->lpVtbl->QueryInterface(plpd->psl, &IID_IPersistFile, &ppf)))
- {
- WCHAR wszPath[MAX_PATH];
- SHTCharToUnicode(plpd->szFile, wszPath, ARRAYSIZE(wszPath));
- hres = ppf->lpVtbl->Load(ppf, wszPath, 0);
- ppf->lpVtbl->Release(ppf);
- if (FAILED(hres))
- {
- LoadString(HINST_THISDLL, IDS_LINKNOTLINK, szBuffer, ARRAYSIZE(szBuffer));
- SetDlgItemText(plpd->hDlg, IDD_FILETYPE, szBuffer);
- _DisableAllChildren(plpd->hDlg);
- DebugMsg(DM_TRACE, TEXT("Shortcut IPersistFile::Load() failed %x"), hres);
- return;
- }
- }
- }
- SHGetFileInfo(plpd->szFile, 0, &sfi, SIZEOF(sfi), SHGFI_DISPLAYNAME | SHGFI_USEFILEATTRIBUTES);
- SetDlgItemText(plpd->hDlg, IDD_NAME, sfi.szDisplayName);
- // we need to check for darwin links here so that we can gray out
- // things that don't apply to darwin
- if (fIsDarwinLink)
- {
- LPEXP_DARWIN_LINK pDarwinData;
- TCHAR szAppState[MAX_PATH];
- DWORD cchAppState = ARRAYSIZE(szAppState);
- HWND hwndTargetType = GetDlgItem(plpd->hDlg, IDD_FILETYPE);
- // disable the children
- _DisableAllChildren(plpd->hDlg);
- // then special case the icon and the "Target type:" text
- _UpdateLinkIcon(plpd, NULL);
- pDarwinData = _GetLinkExtraData(plpd->psl, EXP_DARWIN_ID_SIG);
- if (pDarwinData && IsDarwinAdW(pDarwinData->szwDarwinID))
- {
- // the app is advertised (e.g. not installed), but will be faulted in on first use
- LoadString(HINST_THISDLL, IDS_APP_NOT_FAULTED_IN, szAppState, ARRAYSIZE(szAppState));
- }
- else
- {
- // the darwin app is installed
- LoadString(HINST_THISDLL, IDS_APP_FAULTED_IN, szAppState, ARRAYSIZE(szAppState));
- }
- SetWindowText(hwndTargetType, szAppState);
- EnableWindow(hwndTargetType, TRUE);
- // if we can ge the package name, put that in the Target field
- if (pDarwinData &&
- #ifdef UNICODE
- MsiGetProductInfo(pDarwinData->szwDarwinID,
- INSTALLPROPERTY_PRODUCTNAME,
- szAppState,
- &cchAppState) == ERROR_SUCCESS)
- #else
- MsiGetProductInfo(pDarwinData->szDarwinID,
- INSTALLPROPERTY_PRODUCTNAME,
- szAppState,
- &cchAppState) == ERROR_SUCCESS)
- #endif
- {
- SetWindowText(GetDlgItem(plpd->hDlg, IDD_FILENAME), szAppState);
- }
- if (pDarwinData)
- LocalFree(pDarwinData);
- // we disabled everything in _DisableAllChildren, so re-enable the ones we still apply for darwin
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_NAME), TRUE);
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_PATH), TRUE);
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_LINK_HOTKEY), TRUE);
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_LINK_SHOWCMD), TRUE);
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_LINK_DESCRIPTION), TRUE);
- // we skip all of the gook below if we are darwin since we only support the IDD_NAME, IDD_PATH, IDD_LINK_HOTKEY,
- // IDD_LINK_SHOWCMD, and IDD_LINK_DESCRIPTION fields
- }
- else
- {
- hres = plpd->psl->lpVtbl->GetPath(plpd->psl, szCommand, ARRAYSIZE(szCommand), NULL, SLGP_RAWPATH);
- if (FAILED(hres))
- hres = plpd->psl->lpVtbl->GetPath(plpd->psl, szCommand, ARRAYSIZE(szCommand), NULL, 0);
- if (SUCCEEDED(hres) && (hres != S_FALSE))
- {
- plpd->bIsFile = TRUE;
- // get type
- if (!SHGetFileInfo(szCommand, 0, &sfi, SIZEOF(sfi), SHGFI_TYPENAME))
- {
- TCHAR szExp[MAX_PATH];
- // Let's see if the string has expandable environment strings
- if (SHExpandEnvironmentStrings(szCommand, szExp, ARRAYSIZE(szExp))
- && lstrcmp(szCommand, szExp)) // don't hit the disk a second time if the string hasn't changed
- {
- SHGetFileInfo(szExp, 0, &sfi, SIZEOF(sfi), SHGFI_TYPENAME );
- }
- }
- SetDlgItemText(plpd->hDlg, IDD_FILETYPE, sfi.szTypeName);
- // location
- lstrcpy(szBuffer, szCommand);
- PathRemoveFileSpec(szBuffer);
- SetDlgItemText(plpd->hDlg, IDD_LOCATION, PathFindFileName(szBuffer));
- // command
- plpd->psl->lpVtbl->GetArguments(plpd->psl, szBuffer, ARRAYSIZE(szBuffer));
- PathComposeWithArgs(szCommand, szBuffer);
- GetDlgItemText(plpd->hDlg, IDD_FILENAME, szBuffer, ARRAYSIZE(szBuffer));
- // Conditionally change to prevent "Apply" button from enabling
- if (lstrcmp(szCommand, szBuffer) != 0)
- SetDlgItemText(plpd->hDlg, IDD_FILENAME, szCommand);
- }
- else
- {
- LPITEMIDLIST pidl;
- plpd->bIsFile = FALSE;
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_FILENAME), FALSE);
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_PATH), FALSE);
- plpd->psl->lpVtbl->GetIDList(plpd->psl, &pidl);
- if (pidl)
- {
- SHGetNameAndFlags(pidl, SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, szCommand, SIZECHARS(szCommand), NULL);
- ILRemoveLastID(pidl);
- SHGetNameAndFlags(pidl, SHGDN_NORMAL, szBuffer, SIZECHARS(szBuffer), NULL);
- ILFree(pidl);
- SetDlgItemText(plpd->hDlg, IDD_LOCATION, szBuffer);
- SetDlgItemText(plpd->hDlg, IDD_FILETYPE, szCommand);
- SetDlgItemText(plpd->hDlg, IDD_FILENAME, szCommand);
- }
- }
- #ifdef WINNT
- {
- TCHAR szFullFile[MAX_PATH];
- DWORD cchVerb;
- UINT cch = _GetTargetOfLink(plpd, szFullFile);
- if ((cch != 0) && (cch < ARRAYSIZE(szFullFile)))
- {
- LONG lBinaryType;
- if (GetBinaryType( szFullFile, &lBinaryType) && (lBinaryType == SCS_WOW_BINARY))
- {
- if (_GetLinkFlags(plpd->psl) & SLDF_RUN_IN_SEPARATE)
- {
- // check it
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_RUNINSEPARATE), TRUE);
- CheckDlgButton( plpd->hDlg, IDD_RUNINSEPARATE, 1 );
- }
- else
- {
- // Uncheck it
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_RUNINSEPARATE), TRUE);
- CheckDlgButton( plpd->hDlg, IDD_RUNINSEPARATE, 0 );
- }
- }
- else
- {
- // check it
- CheckDlgButton( plpd->hDlg, IDD_RUNINSEPARATE, 1 );
- EnableWindow(GetDlgItem( plpd->hDlg, IDD_RUNINSEPARATE ), FALSE);
- }
- }
- else
- {
- // check it
- CheckDlgButton( plpd->hDlg, IDD_RUNINSEPARATE, 1 );
- EnableWindow( GetDlgItem( plpd->hDlg, IDD_RUNINSEPARATE ), FALSE );
- }
- // enable "runas" if the link target has that verb
- if (SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, szFullFile, TEXT("runas"), NULL, &cchVerb)) &&
- cchVerb)
- {
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_LINK_RUNASUSER), TRUE);
- CheckDlgButton(plpd->hDlg, IDD_LINK_RUNASUSER, (_GetLinkFlags(plpd->psl) & SLDF_RUNAS_USER) ? BST_CHECKED : BST_UNCHECKED);
- }
- else
- {
- EnableWindow(GetDlgItem(plpd->hDlg, IDD_LINK_RUNASUSER), FALSE);
- CheckDlgButton(plpd->hDlg, IDD_LINK_RUNASUSER, BST_UNCHECKED);
- _SetLinkFlags(plpd->psl, _GetLinkFlags(plpd->psl) & ~SLDF_RUNAS_USER);
- }
- }
- #endif
- }
- if (bUpdatePath)
- return;
- plpd->psl->lpVtbl->GetWorkingDirectory(plpd->psl, szBuffer, ARRAYSIZE(szBuffer));
- SetDlgItemPath(plpd->hDlg, IDD_PATH, szBuffer);
- plpd->psl->lpVtbl->GetDescription(plpd->psl, szBuffer, ARRAYSIZE(szBuffer));
- SetDlgItemText(plpd->hDlg, IDD_LINK_DESCRIPTION, szBuffer);
- plpd->psl->lpVtbl->GetHotkey(plpd->psl, &wHotkey);
- SendDlgItemMessage(plpd->hDlg, IDD_LINK_HOTKEY, HKM_SETHOTKEY, wHotkey, 0);
- //
- // Now initialize the Run SHOW Command combo box
- //
- for (iShowCmd = IDS_RUN_NORMAL; iShowCmd <= IDS_RUN_MAXIMIZED; iShowCmd++)
- {
- LoadString(HINST_THISDLL, iShowCmd, szBuffer, ARRAYSIZE(szBuffer));
- SendDlgItemMessage(plpd->hDlg, IDD_LINK_SHOWCMD, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)szBuffer);
- }
- // Now setup the Show Command - Need to map to index numbers...
- plpd->psl->lpVtbl->GetShowCmd(plpd->psl, &iShowCmd);
- for (i = 0; i < ARRAYSIZE(c_iShowCmds); i++)
- {
- if (c_iShowCmds[i] == iShowCmd)
- break;
- }
- if (i == ARRAYSIZE(c_iShowCmds))
- {
- ASSERT(0); // bogus link show cmd
- i = 0; // SW_SHOWNORMAL
- }
- SendDlgItemMessage(plpd->hDlg, IDD_LINK_SHOWCMD, CB_SETCURSEL, i, 0);
- // the icon
- _UpdateLinkIcon(plpd, NULL);
- }
- //
- // Opens a folder window with the target of the link selected
- //
- void _FindTarget(LPLINKPROP_DATA plpd)
- {
- USHORT uSave;
- LPITEMIDLIST pidl, pidlDesk, pidlLast;
- if (plpd->psl->lpVtbl->Resolve(plpd->psl, plpd->hDlg, 0) != NOERROR)
- return; // above already did UI if needed
- _UpdateLinkDlg(plpd, TRUE);
- plpd->psl->lpVtbl->GetIDList(plpd->psl, &pidl);
- if (!pidl)
- return;
- pidlLast = ILFindLastID(pidl);
- // get the folder, special case for root objects (My Computer, Network)
- // hack off the end if it is not the root item
- if (pidl != pidlLast)
- {
- uSave = pidlLast->mkid.cb;
- pidlLast->mkid.cb = 0;
- }
- else
- uSave = 0;
- pidlDesk = SHCloneSpecialIDList(NULL, CSIDL_DESKTOPDIRECTORY, FALSE);
- if (pidlDesk)
- {
- BOOL fIsDesktopDir = ILIsEqual(pidl, pidlDesk);
- if (fIsDesktopDir || !uSave) // if it's in the desktop dir or pidl == pidlLast (uSave == 0 from above)
- {
- ShellMessageBox(HINST_THISDLL, plpd->hDlg, MAKEINTRESOURCE(IDS_ORIGINALONDESKTOP), NULL, MB_OK);
- // get keyboard focus to the desktop (away from this prop sheet)
- PostMessage(plpd->hDlg, LNKM_ACTIVATEOTHER, 0, (LPARAM)FindWindow(TEXT(STR_DESKTOPCLASS), NULL));
- }
- else
- {
- IShellFolderViewDual *psfv;
- if (SUCCEEDED(OpenContainingFolderAndGetShellFolderView(uSave ? pidl : pidlDesk, &psfv)))
- {
- if (uSave)
- pidlLast->mkid.cb = uSave;
- SelectPidlInSFV(psfv, pidlLast, SVSI_SELECT | SVSI_FOCUSED | SVSI_DESELECTOTHERS | SVSI_ENSUREVISIBLE);
- psfv->lpVtbl->Release(psfv);
- }
- }
- ILFree(pidlDesk);
- }
- ILFree(pidl);
- }
- // let the user pick a new icon for a link...
- BOOL _DoPickIcon(LPLINKPROP_DATA plpd)
- {
- int iIconIndex;
- SHFILEINFO sfi;
- TCHAR *pszIconPath = sfi.szDisplayName;
- IShellLinkDataList *psldl;
- EXP_SZ_LINK *esli;
- HRESULT hr;
- *pszIconPath = 0;
- //
- // if the user has picked a icon before use it.
- //
- if (plpd->szIconPath[0] != 0 && plpd->iIconIndex >= 0)
- {
- lstrcpy(pszIconPath, plpd->szIconPath);
- iIconIndex = plpd->iIconIndex;
- }
- else
- {
- //
- // if this link has a icon use that.
- //
- plpd->psl->lpVtbl->GetIconLocation(plpd->psl, pszIconPath, MAX_PATH, &iIconIndex);
- //
- // check for an escaped version, if its there, use that
- //
- if (SUCCEEDED(hr = plpd->psl->lpVtbl->QueryInterface(plpd->psl, &IID_IShellLinkDataList, (LPVOID*)&psldl)))
- {
- if (SUCCEEDED(hr = psldl->lpVtbl->CopyDataBlock(psldl, EXP_SZ_ICON_SIG, (LPVOID*)&esli)))
- {
- ASSERT(esli);
- #ifdef UNICODE
- lstrcpyn(pszIconPath, esli->swzTarget, MAX_PATH);
- #else
- lstrcpyn(pszIconPath, esli->szTarget, MAX_PATH);
- #endif
- LocalFree(esli);
- }
- psldl->lpVtbl->Release(psldl);
- }
- if (pszIconPath[0] == TEXT('.'))
- {
- TCHAR szFullIconPath[MAX_PATH];
- // We now allow ".txt" for the icon path, but since the user is clicking
- // on the "Change Icon..." button, we show the current icon that ".txt" is
- // associated with
- GetIconLocationFromExt(pszIconPath, szFullIconPath, ARRAYSIZE(szFullIconPath), &iIconIndex);
- lstrcpyn(pszIconPath, szFullIconPath, ARRAYSIZE(sfi.szDisplayName));
- }
- else if (pszIconPath[0] == TEXT(''))
- {
- //
- // link does not have a icon, if it is a link to a file
- // use the file name
- //
- TCHAR szArgs[MAX_PATH];
- _GetPathAndArgs(plpd, pszIconPath, szArgs);
- iIconIndex = 0;
- if (!plpd->bIsFile || !PathIsExe(pszIconPath))
- {
- //
- // link is not to a file, go get the icon
- //
- SHGetFileInfo(plpd->szFile, 0, &sfi, SIZEOF(sfi), SHGFI_ICONLOCATION);
- iIconIndex = sfi.iIcon;
- ASSERT(pszIconPath == sfi.szDisplayName);
- }
- }
- }
- if (PickIconDlg(plpd->hDlg, pszIconPath, MAX_PATH, &iIconIndex))
- {
- HICON hIcon = ExtractIcon(HINST_THISDLL, pszIconPath, iIconIndex);
- _UpdateLinkIcon(plpd, hIcon);
- // don't save it out to the link yet, just store it in our instance data
- plpd->iIconIndex = iIconIndex;
- lstrcpy(plpd->szIconPath, pszIconPath);
- PropSheet_Changed(GetParent(plpd->hDlg), plpd->hDlg);
- return TRUE;
- }
- return FALSE;
- }
- HRESULT _SaveLink(LPLINKDATA pld)
- {
- WORD wHotkey;
- int iShowCmd;
- IPersistFile *ppf;
- HRESULT hres;
- TCHAR szBuffer[MAX_PATH];
- #ifdef WINNT
- if (!(pld->lpd.bIsDirty || (pld->cpd.lpConsole && pld->cpd.bConDirty)))
- #else
- if (!pld->lpd.bIsDirty)
- #endif
- return S_OK;
- if (pld->lpd.bIsFile)
- {
- TCHAR szBuffer[MAX_PATH];
- TCHAR szArgs[MAX_PATH];
- _GetPathAndArgs(&pld->lpd, szBuffer, szArgs);
- // set the path (and pidl) of the link
- pld->lpd.psl->lpVtbl->SetPath(pld->lpd.psl, szBuffer);
- // may be null
- pld->lpd.psl->lpVtbl->SetArguments(pld->lpd.psl, szArgs);
- #ifdef WINNT
- {
- DWORD dwOldFlags = _GetLinkFlags(pld->lpd.psl);
- // Set whether to run in separate memory space
- dwOldFlags &= ~SLDF_RUN_IN_SEPARATE;
- _SetLinkFlags(pld->lpd.psl, dwOldFlags);
- if (IsWindowEnabled( GetDlgItem( pld->lpd.hDlg, IDD_RUNINSEPARATE )))
- {
- if (IsDlgButtonChecked( pld->lpd.hDlg, IDD_RUNINSEPARATE ))
- _SetLinkFlags(pld->lpd.psl, dwOldFlags | SLDF_RUN_IN_SEPARATE);
- }
- dwOldFlags = _GetLinkFlags(pld->lpd.psl);
- if (IsWindowEnabled(GetDlgItem(pld->lpd.hDlg, IDD_LINK_RUNASUSER)) &&
- IsDlgButtonChecked(pld->lpd.hDlg, IDD_LINK_RUNASUSER))
- {
- _SetLinkFlags(pld->lpd.psl, dwOldFlags | SLDF_RUNAS_USER);
- }
- else
- {
- _SetLinkFlags(pld->lpd.psl, dwOldFlags & ~SLDF_RUNAS_USER);
- }
- }
- #endif
- }
- if (pld->lpd.bIsFile || (_GetLinkFlags(pld->lpd.psl) & SLDF_HAS_DARWINID))
- {
- // set the working directory of the link
- GetDlgItemPath(pld->lpd.hDlg, IDD_PATH, szBuffer);
- pld->lpd.psl->lpVtbl->SetWorkingDirectory(pld->lpd.psl, szBuffer);
- }
- // set the description of the link
- GetDlgItemText(pld->lpd.hDlg, IDD_LINK_DESCRIPTION, szBuffer, MAX_PATH);
- pld->lpd.psl->lpVtbl->SetDescription(pld->lpd.psl, szBuffer);
- // the hotkey
- wHotkey = (WORD)SendDlgItemMessage(pld->lpd.hDlg, IDD_LINK_HOTKEY , HKM_GETHOTKEY, 0, 0);
- pld->lpd.psl->lpVtbl->SetHotkey(pld->lpd.psl, wHotkey);
- // the show command combo box
- iShowCmd = (int)SendDlgItemMessage(pld->lpd.hDlg, IDD_LINK_SHOWCMD, CB_GETCURSEL, 0, 0L);
- if ((iShowCmd >= 0) && (iShowCmd < ARRAYSIZE(c_iShowCmds)))
- pld->lpd.psl->lpVtbl->SetShowCmd(pld->lpd.psl, c_iShowCmds[iShowCmd]);
- // If the user explicitly selected a new icon, invalidate
- // the icon cache entry for this link and then send around a file
- // sys refresh message to all windows in case they are looking at
- // this link.
- if (pld->lpd.iIconIndex >= 0)
- pld->lpd.psl->lpVtbl->SetIconLocation(pld->lpd.psl, pld->lpd.szIconPath, pld->lpd.iIconIndex);
- #ifdef WINNT
- // Update/Save the console information in the pExtraData section of
- // the shell link.
- if (pld->cpd.lpConsole && pld->cpd.bConDirty)
- LinkConsolePagesSave( pld );
- #endif
- hres = pld->lpd.psl->lpVtbl->QueryInterface(pld->lpd.psl, &IID_IPersistFile, &ppf);
- if (SUCCEEDED(hres))
- {
- if (ppf->lpVtbl->IsDirty(ppf) == NOERROR)
- {
- // save using existing file name (pld->lpd.szFile)
- hres = ppf->lpVtbl->Save(ppf, NULL, TRUE);
- if (FAILED(hres))
- {
- SHSysErrorMessageBox(pld->lpd.hDlg, NULL, IDS_LINKCANTSAVE,
- hres & 0xFFF, PathFindFileName(pld->lpd.szFile),
- MB_OK | MB_ICONEXCLAMATION);
- }
- else
- {
- pld->lpd.bIsDirty = FALSE;
- }
- }
- ppf->lpVtbl->Release(ppf);
- }
- return hres;
- }
- void SetEditFocus(HWND hwnd)
- {
- SetFocus(hwnd);
- Edit_SetSel(hwnd, 0, -1);
- }
- // returns:
- // TRUE all link fields are valid
- // FALSE some thing is wrong with what the user has entered
- BOOL _ValidateLink(LPLINKPROP_DATA plpd)
- {
- TCHAR szDir[MAX_PATH], szPath[MAX_PATH], szArgs[MAX_PATH];
- TCHAR szExpPath[MAX_PATH];
- LPTSTR dirs[2];
- BOOL bValidPath = FALSE;
- if (!plpd->bIsFile)
- return TRUE;
- // validate the working directory field
- GetDlgItemPath(plpd->hDlg, IDD_PATH, szDir);
- if (*szDir &&
- StrChr(szDir, TEXT('%')) == NULL && // has environement var %USER%
- !IsRemovableDrive(DRIVEID(szDir)) &&
- !PathIsDirectory(szDir))
- {
- ShellMessageBox(HINST_THISDLL, plpd->hDlg, MAKEINTRESOURCE(IDS_LINKBADWORKDIR),
- MAKEINTRESOURCE(IDS_LINKERROR), MB_OK | MB_ICONEXCLAMATION, szDir);
- SetEditFocus(GetDlgItem(plpd->hDlg, IDD_PATH));
- return FALSE;
- }
- // validate the path (with arguments) field
- _GetPathAndArgs(plpd, szPath, szArgs);
- if (szPath[0] == 0)
- return TRUE;
- if (PathIsRoot(szPath) && IsRemovableDrive(DRIVEID(szPath)))
- return TRUE;
- if (PathIsLnk(szPath))
- {
- ShellMessageBox(HINST_THISDLL, plpd->hDlg, MAKEINTRESOURCE(IDS_LINKTOLINK),
- MAKEINTRESOURCE(IDS_LINKERROR), MB_OK | MB_ICONEXCLAMATION);
- SetEditFocus(GetDlgItem(plpd->hDlg, IDD_FILENAME));
- return FALSE;
- }
- dirs[0] = szDir;
- dirs[1] = NULL;
- bValidPath = PathResolve(szPath, dirs, PRF_DONTFINDLNK | PRF_TRYPROGRAMEXTENSIONS);
- if (!bValidPath)
- {
- // The path "as is" was invalid. See if it has environment variables
- // which need to be expanded.
- _GetPathAndArgs(plpd, szPath, szArgs);
- if (SHExpandEnvironmentStrings(szPath, szExpPath, ARRAYSIZE(szExpPath)))
- {
- if (PathIsRoot(szExpPath) && IsRemovableDrive(DRIVEID(szDir)))
- return TRUE;
- bValidPath = PathResolve(szExpPath, dirs, PRF_DONTFINDLNK | PRF_TRYPROGRAMEXTENSIONS);
- }
- }
- if (bValidPath)
- {
- #ifdef WINNT
- BOOL bSave;
- if (plpd->hThread)
- {
- bSave = plpd->bCheckRunInSep;
- plpd->bCheckRunInSep = FALSE;
- }
- #endif
- PathComposeWithArgs(szPath, szArgs);
- GetDlgItemText(plpd->hDlg, IDD_FILENAME, szExpPath, ARRAYSIZE(szExpPath));
- // only do this if something changed... that way we avoid having the PSM_CHANGED
- // for nothing
- if (lstrcmpi(szPath, szExpPath))
- SetDlgItemText(plpd->hDlg, IDD_FILENAME, szPath);
- #ifdef WINNT
- if (plpd->hThread)
- {
- plpd->bCheckRunInSep = bSave;
- }
- #endif
- return TRUE;
- }
- ShellMessageBox(HINST_THISDLL, plpd->hDlg, MAKEINTRESOURCE(IDS_LINKBADPATH),
- MAKEINTRESOURCE(IDS_LINKERROR), MB_OK | MB_ICONEXCLAMATION, szPath);
- SetEditFocus(GetDlgItem(plpd->hDlg, IDD_FILENAME));
- return FALSE;
- }
- // Array for context help:
- const DWORD aLinkHelpIDs[] = {
- IDD_LINE_1, NO_HELP,
- IDD_LINE_2, NO_HELP,
- IDD_ITEMICON, IDH_FCAB_LINK_ICON,
- IDD_NAME, IDH_FCAB_LINK_NAME,
- IDD_FILETYPE_TXT, IDH_FCAB_LINK_LINKTYPE,
- IDD_FILETYPE, IDH_FCAB_LINK_LINKTYPE,
- IDD_LOCATION_TXT, IDH_FCAB_LINK_LOCATION,
- IDD_LOCATION, IDH_FCAB_LINK_LOCATION,
- IDD_FILENAME, IDH_FCAB_LINK_LINKTO,
- IDD_PATH, IDH_FCAB_LINK_WORKING,
- IDD_LINK_HOTKEY, IDH_FCAB_LINK_HOTKEY,
- IDD_LINK_SHOWCMD, IDH_FCAB_LINK_RUN,
- IDD_LINK_DESCRIPTION, IDH_FCAB_LINK_DESCRIPTION,
- IDD_FINDORIGINAL, IDH_FCAB_LINK_FIND,
- IDD_LINKDETAILS, IDH_FCAB_LINK_CHANGEICON,
- #ifdef WINNT
- IDD_RUNINSEPARATE, IDH_TRAY_RUN_SEPMEM,
- IDD_LINK_RUNASUSER, IDH_FCAB_LINK_RUNASUSER,
- #endif
- 0, 0
- };
- // Dialog proc for the generic link property sheet
- //
- // uses DLG_LINKPROP template
- //
- BOOL_PTR CALLBACK _LinkDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- LPLINKDATA pld = (LPLINKDATA)GetWindowLongPtr(hdlg, DWLP_USER);
- switch (msg) {
- case WM_INITDIALOG:
- pld = (LPLINKDATA)((PROPSHEETPAGE *)lParam)->lParam;
- SetWindowLongPtr(hdlg, DWLP_USER, (LPARAM)pld);
- // setup dialog state variables
- pld->lpd.hDlg = hdlg;
- SendDlgItemMessage(hdlg, IDD_FILENAME, EM_LIMITTEXT, MAX_PATH-1, 0);
- SetPathWordBreakProc(GetDlgItem(hdlg, IDD_FILENAME), TRUE);
- SendDlgItemMessage(hdlg, IDD_PATH, EM_LIMITTEXT, MAX_PATH-1, 0);
- SetPathWordBreakProc(GetDlgItem(hdlg, IDD_PATH), TRUE);
- SendDlgItemMessage(hdlg, IDD_LINK_DESCRIPTION, EM_LIMITTEXT, MAX_PATH-1, 0);
- // set valid combinations for the hotkey
- SendDlgItemMessage(hdlg, IDD_LINK_HOTKEY, HKM_SETRULES,
- HKCOMB_NONE | HKCOMB_A | HKCOMB_S | HKCOMB_C,
- HOTKEYF_CONTROL | HOTKEYF_ALT);
- SHAutoComplete(GetDlgItem(hdlg, IDD_FILENAME), 0);
- SHAutoComplete(GetDlgItem(hdlg, IDD_PATH), 0);
- #ifdef WINNT
- ASSERT(pld->lpd.hThread == NULL);
- #endif
- _UpdateLinkDlg(&pld->lpd, FALSE);
- // Set up background thread to handle "Run In Separate Memory Space"
- // check box.
- #ifdef WINNT
- pld->lpd.bCheckRunInSep = TRUE;
- pld->lpd.hCheckNow = CreateEvent( NULL, TRUE, FALSE, NULL );
- if (pld->lpd.hCheckNow)
- {
- DWORD dwDummy;
- pld->lpd.hThread = CreateThread(NULL, 0, _LinkCheckThreadProc, &pld->lpd, 0, &dwDummy);
- if (pld->lpd.hThread == NULL)
- {
- CloseHandle(pld->lpd.hCheckNow);
- pld->lpd.hCheckNow = NULL;
- }
- }
- #endif
- // start off clean.
- // do this here because we call some stuff above which generates
- // wm_command/en_changes which we then think makes it dirty
- pld->lpd.bIsDirty = FALSE;
- break;
- #ifdef WINNT
- case WM_DESTROY:
- _StopThread(&pld->lpd);
- break;
- #endif
- case WM_NOTIFY:
- switch (((NMHDR *)lParam)->code) {
- #ifdef WINNT
- case PSN_RESET:
- _StopThread(&pld->lpd);
- break;
- #endif
- case PSN_APPLY:
- #ifdef WINNT
- if ((((PSHNOTIFY *)lParam)->lParam))
- _StopThread(&pld->lpd);
- #endif
- if (FAILED(_SaveLink(pld)))
- SetWindowLongPtr(hdlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
- break;
- case PSN_KILLACTIVE:
- // we implement the save on page change model, so
- // validate and save changes here. this works for
- // Apply Now, OK, and Page chagne.
- SetWindowLongPtr(hdlg, DWLP_MSGRESULT, !_ValidateLink(&pld->lpd)); // don't allow close
- break;
- }
- break;
- case WM_COMMAND:
- switch (GET_WM_COMMAND_ID(wParam, lParam)) {
- case IDD_FINDORIGINAL:
- _FindTarget(&pld->lpd);
- break;
- case IDD_LINKDETAILS:
- if (_DoPickIcon(&pld->lpd))
- pld->lpd.bIsDirty = TRUE;
- break;
- case IDD_LINK_SHOWCMD:
- if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE)
- {
- PropSheet_Changed(GetParent(hdlg), hdlg);
- pld->lpd.bIsDirty = TRUE;
- }
- break;
- #ifdef WINNT
- case IDD_RUNINSEPARATE:
- if (IsWindowEnabled( GetDlgItem( hdlg, IDD_RUNINSEPARATE )) )
- {
- PropSheet_Changed(GetParent(hdlg), hdlg);
- pld->lpd.bIsDirty = TRUE;
- }
- break;
- case IDD_LINK_RUNASUSER:
- if (IsWindowEnabled(GetDlgItem(hdlg, IDD_LINK_RUNASUSER)))
- {
- PropSheet_Changed(GetParent(hdlg), hdlg);
- pld->lpd.bIsDirty = TRUE;
- }
- break;
- #endif
- case IDD_LINK_HOTKEY:
- case IDD_FILENAME:
- case IDD_PATH:
- case IDD_LINK_DESCRIPTION:
- if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
- {
- PropSheet_Changed(GetParent(hdlg), hdlg);
- pld->lpd.bIsDirty = TRUE;
- #ifdef WINNT
- if (pld->lpd.hThread && pld->lpd.bCheckRunInSep)
- SetEvent( pld->lpd.hCheckNow );
- #endif
- }
- break;
- default:
- return FALSE;
- }
- break;
- case LNKM_ACTIVATEOTHER:
- SwitchToThisWindow(GetLastActivePopup((HWND)lParam), TRUE);
- SetForegroundWindow((HWND)lParam);
- break;
- case WM_HELP:
- WinHelp(((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aLinkHelpIDs);
- break;
- case WM_CONTEXTMENU:
- WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(LPVOID)aLinkHelpIDs);
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- //
- // Release the link object allocated during the initialize
- //
- UINT CALLBACK _LinkPrshtCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
- {
- LPLINKDATA pld = (LPLINKDATA)((PROPSHEETPAGE *)ppsp->lParam);
- switch (uMsg) {
- case PSPCB_RELEASE:
- #ifdef WINNT
- if (pld->cpd.lpConsole)
- {
- LocalFree(pld->cpd.lpConsole );
- }
- if (pld->cpd.lpFEConsole)
- {
- LocalFree(pld->cpd.lpFEConsole );
- }
- DestroyFonts( &pld->cpd );
- #endif
- pld->lpd.psl->lpVtbl->Release(pld->lpd.psl);
- LocalFree(pld);
- break;
- }
- return 1;
- }
- BOOL AddLinkPage(LPCTSTR pszFile, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
- {
- IShellLink *psl;
- // HACK: call constuctor directly (should use CoCreateInstance())
- // NOTE: do not call CoCreateInstance, because then you are not guranteed
- // to get our CShellLink implementation, and we pass this object
- // on to AddLinkConsolePages which assumes it is a CShellLink object.
- if (PathIsLnk(pszFile) && SUCCEEDED(CShellLink_CreateInstance(NULL, &IID_IShellLink, &psl)))
- {
- // alloc this data, since is it shared across several pages
- // instead of putting it in as extra data in the page header
- LPLINKDATA pld = LocalAlloc(LPTR, SIZEOF(LINKDATA));
- if (pld)
- {
- HPROPSHEETPAGE hpage;
- PROPSHEETPAGE psp;
- psp.dwSize = SIZEOF( psp );
- psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
- psp.hInstance = HINST_THISDLL;
- psp.pszTemplate = MAKEINTRESOURCE(DLG_LINKPROP);
- psp.pfnDlgProc = _LinkDlgProc;
- psp.pfnCallback = _LinkPrshtCallback;
- psp.lParam = (LPARAM)pld; // pass to all dlg procs
- lstrcpyn(pld->lpd.szFile, pszFile, ARRAYSIZE(pld->lpd.szFile));
- // pld->lpd.hThread = NULL; // zero-init allo
- // pld->lpd.szIconPath[0] = 0;
- pld->lpd.iIconIndex = -1;
- pld->lpd.psl = psl;
- ASSERT(!pld->lpd.szIconPath[0]);
- hpage = CreatePropertySheetPage( &psp );
- if (hpage)
- {
- if (pfnAddPage(hpage, lParam))
- {
- #ifdef WINNT
- // Add console property pages if appropriate...
- AddLinkConsolePages( pld, psl, pszFile, pfnAddPage, lParam );
- #endif
- return TRUE; // we added the link page
- }
- else
- {
- DestroyPropertySheetPage(hpage);
- }
- }
- LocalFree(pld);
- }
- psl->lpVtbl->Release(psl);
- }
- return FALSE;
- }