From: Aric Stewart aric@codeweavers.com
--- dlls/shell32/shell32.rc | 1 + dlls/shell32/shlview_cmenu.c | 113 +++++++++++++++++++++++++++++++++++ dlls/shell32/shresdef.h | 2 + 3 files changed, 116 insertions(+)
diff --git a/dlls/shell32/shell32.rc b/dlls/shell32/shell32.rc index f1b0bc50cca..55632a1539d 100644 --- a/dlls/shell32/shell32.rc +++ b/dlls/shell32/shell32.rc @@ -250,6 +250,7 @@ the folder?" IDS_RECYCLEBIN_OVERWRITEFILE "A file already exists at the path %1.\n\nDo you want to replace it?" IDS_RECYCLEBIN_OVERWRITEFOLDER "A folder already exists at the path %1.\n\nDo you want to replace it?" IDS_RECYCLEBIN_OVERWRITE_CAPTION "Confirm overwrite" + IDS_SHORTCUT "Shortcut" }
STRINGTABLE diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c index cac33c39af7..dae9ae8c2b0 100644 --- a/dlls/shell32/shlview_cmenu.c +++ b/dlls/shell32/shlview_cmenu.c @@ -946,6 +946,116 @@ static void DoOpenProperties(ContextMenu *This, HWND hwnd) FIXME("No property pages found.\n"); }
+ +static HRESULT do_create_link(ContextMenu *This) +{ + IShellLinkW* shelllink; + IPersistFile* persistfile; + WCHAR filename[MAX_PATH]; + WCHAR root[MAX_PATH]; + WCHAR lnkfile[MAX_PATH]; + ITEMIDLIST *full_pidl; + HRESULT hr = S_OK; + int counter = 1; + WCHAR shortcutW[255]; + WCHAR *link_filename; + int length; /* length of the format*/ + + LoadStringW(shell32_hInstance, IDS_SHORTCUT, shortcutW, ARRAY_SIZE(shortcutW)); + + if (FAILED(hr = IShellLink_Constructor(NULL, &IID_IShellLinkW, (LPVOID*)&shelllink))) + { + ERR("couldn't create ShellLink object\n"); + return hr; + } + full_pidl = ILCombine(This->pidl, This->apidl[0]); + if (!full_pidl) + { + ERR("Out of Memory\n"); + IShellLinkW_Release(shelllink); + return E_OUTOFMEMORY; + } + + hr = IShellLinkW_SetIDList(shelllink, full_pidl); + ILFree(full_pidl); + if (FAILED(hr)) + { + ERR("SetIDList failed\n"); + IShellLinkW_Release(shelllink); + return hr; + } + + if (!_ILSimpleGetTextW(This->apidl[0], (LPVOID)filename, MAX_PATH)) + { + ERR("Failed to get Path Text\n"); + IShellLinkW_Release(shelllink); + return E_FAIL; + } + + if (!SHGetPathFromIDListW(This->pidl, root)) + { + /* Special PIDL, use the desktop */ + if (FAILED(SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, root))) { + ERR("Failed to get PID path\n"); + IShellLinkW_Release(shelllink); + return E_FAIL; + } + } + + IShellLinkW_QueryInterface(shelllink, &IID_IPersistFile, (LPVOID*)&persistfile); + length = wcslen(filename) + wcslen(shortcutW) + 41; /* length of the format and counter */ + link_filename = malloc((length + 1) * sizeof(WCHAR)); + if (link_filename == NULL) { + ERR("Memory allocation failed\n"); + IShellLinkW_Release(shelllink); + return E_FAIL; + } + + do { + if (counter == 1) + { + static const WCHAR *fmt = L"%s - %s.lnk"; + wsprintfW(link_filename, fmt, filename, shortcutW); + } + else + { + static const WCHAR *fmt = L"%s - %s (%u).lnk"; + wsprintfW(link_filename, fmt, filename, shortcutW, counter); + } + + length = wcslen(root) + wcslen(link_filename) + 2; /* the path seperator and NULL */ + if (length > MAX_PATH) + { + ERR("Path maximum length exceeded (%i>%i)\n", length, MAX_PATH); + IShellLinkW_Release(shelllink); + free(link_filename); + return E_FAIL; + } + + PathCombineW(lnkfile, root, link_filename); + counter++; + + if (PathFileExistsW(lnkfile)) + { + hr = HRESULT_FROM_WIN32(ERROR_FILE_EXISTS); + } + else + { + hr = IPersistFile_Save(persistfile, lnkfile, FALSE); + } + } while (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)); + + free(link_filename); + + if (FAILED(hr)) + ERR("couldn't write link to %s : %#lx\n", wine_dbgstr_w(lnkfile), hr); + + IPersistFile_Release(persistfile); + IShellLinkW_Release(shelllink); + + return hr; +} + static HRESULT WINAPI ItemMenu_InvokeCommand( IContextMenu3 *iface, LPCMINVOKECOMMANDINFO lpcmi) @@ -1014,6 +1124,9 @@ static HRESULT WINAPI ItemMenu_InvokeCommand( TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n"); DoOpenProperties(This, lpcmi->hwnd); break; + case FCIDM_SHVIEW_CREATELINK: + TRACE("Verb FCIDM_SHVIEW_CREATELINK\n"); + return do_create_link(This); default: FIXME("Unhandled verb %#x.\n", id); return E_INVALIDARG; diff --git a/dlls/shell32/shresdef.h b/dlls/shell32/shresdef.h index deabe568022..429b276fc4d 100644 --- a/dlls/shell32/shresdef.h +++ b/dlls/shell32/shresdef.h @@ -139,6 +139,8 @@
#define IDS_NEW_MENU_FOLDER 180
+#define IDS_SHORTCUT 181 + #define IDS_LICENSE 256 #define IDS_LICENSE_CAPTION 257