2 * PROJECT: ReactOS Software Control Panel
3 * FILE: dll/cpl/appwiz/createlink.c
4 * PURPOSE: ReactOS Software Control Panel
5 * PROGRAMMER: Gero Kuehn (reactos.filter@gkware.com)
6 * Dmitry Chapyshev (lentind@yandex.ru)
8 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
24 if (RegQueryValueExW(hKey
, L
"IsShortcut", NULL
, &Type
, (LPBYTE
)Value
, &Size
) != ERROR_SUCCESS
)
30 return (wcsicmp(Value
, L
"yes") == 0);
34 IsExtensionAShortcut(LPWSTR lpExtension
)
41 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, lpExtension
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
50 Size
= sizeof(Buffer
);
51 if (RegQueryValueEx(hKey
, NULL
, NULL
, &Type
, (LPBYTE
)Buffer
, &Size
) != ERROR_SUCCESS
|| Type
!= REG_SZ
)
59 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, Buffer
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
73 CreateShortcut(PCREATE_LINK_CONTEXT pContext
)
75 IShellLinkW
*pShellLink
, *pSourceShellLink
;
76 IPersistFile
*pPersistFile
;
81 /* get the extension */
82 lpExtension
= PathFindExtensionW(pContext
->szTarget
);
84 if (IsExtensionAShortcut(lpExtension
))
86 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_ALL
, &IID_IShellLinkW
, (void**)&pSourceShellLink
);
91 hr
= IUnknown_QueryInterface(pSourceShellLink
, &IID_IPersistFile
, (void**)&pPersistFile
);
94 IUnknown_Release(pSourceShellLink
);
98 hr
= pPersistFile
->lpVtbl
->Load(pPersistFile
, (LPCOLESTR
)pContext
->szTarget
, STGM_READ
);
99 IUnknown_Release(pPersistFile
);
103 IUnknown_Release(pSourceShellLink
);
107 hr
= IShellLinkW_GetPath(pSourceShellLink
, Path
, _countof(Path
), NULL
, 0);
108 IUnknown_Release(pSourceShellLink
);
117 StringCchCopyW(Path
, _countof(Path
), pContext
->szTarget
);
120 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_ALL
,
121 &IID_IShellLinkW
, (void**)&pShellLink
);
126 pShellLink
->lpVtbl
->SetPath(pShellLink
, Path
);
127 pShellLink
->lpVtbl
->SetDescription(pShellLink
, pContext
->szDescription
);
128 pShellLink
->lpVtbl
->SetWorkingDirectory(pShellLink
, pContext
->szWorkingDirectory
);
130 hr
= IUnknown_QueryInterface(pShellLink
, &IID_IPersistFile
, (void**)&pPersistFile
);
133 IUnknown_Release(pShellLink
);
137 hr
= pPersistFile
->lpVtbl
->Save(pPersistFile
, pContext
->szLinkName
, TRUE
);
138 IUnknown_Release(pPersistFile
);
139 IUnknown_Release(pShellLink
);
144 CreateInternetShortcut(PCREATE_LINK_CONTEXT pContext
)
146 IUniformResourceLocatorW
*pURL
= NULL
;
147 IPersistFile
*pPersistFile
= NULL
;
149 WCHAR szPath
[MAX_PATH
];
150 GetFullPathNameW(pContext
->szLinkName
, _countof(szPath
), szPath
, NULL
);
152 hr
= CoCreateInstance(&CLSID_InternetShortcut
, NULL
, CLSCTX_ALL
,
153 &IID_IUniformResourceLocatorW
, (void **)&pURL
);
157 hr
= IUnknown_QueryInterface(pURL
, &IID_IPersistFile
, (void **)&pPersistFile
);
160 IUnknown_Release(pURL
);
164 pURL
->lpVtbl
->SetURL(pURL
, pContext
->szTarget
, 0);
166 hr
= pPersistFile
->lpVtbl
->Save(pPersistFile
, szPath
, TRUE
);
168 IUnknown_Release(pPersistFile
);
169 IUnknown_Release(pURL
);
171 return SUCCEEDED(hr
);
174 BOOL
IsInternetLocation(LPCWSTR pszLocation
)
176 return (PathIsURLW(pszLocation
) || wcsstr(pszLocation
, L
"www.") == pszLocation
);
181 WelcomeDlgProc(HWND hwndDlg
,
186 LPPROPSHEETPAGEW ppsp
;
187 PCREATE_LINK_CONTEXT pContext
;
189 WCHAR szPath
[MAX_PATH
];
192 LPITEMIDLIST pidllist
;
197 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
198 pContext
= (PCREATE_LINK_CONTEXT
) ppsp
->lParam
;
199 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pContext
);
200 PropSheet_SetWizButtons(GetParent(hwndDlg
), 0);
203 switch(HIWORD(wParam
))
206 if (SendDlgItemMessage(hwndDlg
, IDC_SHORTCUT_LOCATION
, WM_GETTEXTLENGTH
, 0, 0))
208 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
);
212 PropSheet_SetWizButtons(GetParent(hwndDlg
), 0);
216 switch(LOWORD(wParam
))
218 case IDC_SHORTCUT_BROWSE
:
219 ZeroMemory(&brws
, sizeof(brws
));
220 brws
.hwndOwner
= hwndDlg
;
221 brws
.pidlRoot
= NULL
;
222 brws
.pszDisplayName
= szPath
;
223 brws
.ulFlags
= BIF_BROWSEINCLUDEFILES
;
225 pidllist
= SHBrowseForFolderW(&brws
);
229 if (SHGetPathFromIDListW(pidllist
, szPath
))
230 SetDlgItemTextW(hwndDlg
, IDC_SHORTCUT_LOCATION
, szPath
);
232 /* Free memory, if possible */
233 CoTaskMemFree(pidllist
);
238 lppsn
= (LPPSHNOTIFY
) lParam
;
239 if (lppsn
->hdr
.code
== PSN_WIZNEXT
)
242 pContext
= (PCREATE_LINK_CONTEXT
) GetWindowLongPtr(hwndDlg
, DWLP_USER
);
243 GetDlgItemTextW(hwndDlg
, IDC_SHORTCUT_LOCATION
, pContext
->szTarget
, _countof(pContext
->szTarget
));
244 StrTrimW(pContext
->szTarget
, L
" \t");
246 if (IsInternetLocation(pContext
->szTarget
))
250 LoadStringW(hApplet
, IDS_NEW_INTERNET_SHORTCUT
, szName
, _countof(szName
));
251 StringCchCopyW(pContext
->szDescription
, _countof(pContext
->szDescription
), szName
);
253 pContext
->szWorkingDirectory
[0] = 0;
255 else if (GetFileAttributesW(pContext
->szTarget
) != INVALID_FILE_ATTRIBUTES
)
258 SendDlgItemMessage(hwndDlg
, IDC_SHORTCUT_LOCATION
, EM_SETSEL
, 0, -1);
259 SetFocus(GetDlgItem(hwndDlg
, IDC_SHORTCUT_LOCATION
));
260 SetWindowLongPtr(hwndDlg
, DWLP_MSGRESULT
, PSNRET_INVALID_NOCHANGEPAGE
);
262 /* set working directory */
263 StringCchCopyW(pContext
->szWorkingDirectory
, _countof(pContext
->szWorkingDirectory
),
265 PathRemoveBackslashW(pContext
->szWorkingDirectory
);
266 pch
= PathFindFileNameW(pContext
->szWorkingDirectory
);
269 PathRemoveBackslashW(pContext
->szWorkingDirectory
);
274 WCHAR szError
[MAX_PATH
+ 100];
275 LoadStringW(hApplet
, IDS_CREATE_SHORTCUT
, szDesc
, _countof(szDesc
));
276 LoadStringW(hApplet
, IDS_ERROR_NOT_FOUND
, szPath
, _countof(szPath
));
277 StringCchPrintfW(szError
, _countof(szError
), szPath
, pContext
->szTarget
);
278 MessageBoxW(hwndDlg
, szError
, szDesc
, MB_ICONERROR
);
288 FinishDlgProc(HWND hwndDlg
,
293 LPPROPSHEETPAGEW ppsp
;
294 PCREATE_LINK_CONTEXT pContext
;
300 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
301 pContext
= (PCREATE_LINK_CONTEXT
) ppsp
->lParam
;
302 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pContext
);
303 SetDlgItemTextW(hwndDlg
, IDC_SHORTCUT_NAME
, pContext
->szDescription
);
304 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_FINISH
);
307 switch(HIWORD(wParam
))
310 if (SendDlgItemMessage(hwndDlg
, IDC_SHORTCUT_NAME
, WM_GETTEXTLENGTH
, 0, 0))
312 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_FINISH
);
316 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
);
322 lppsn
= (LPPSHNOTIFY
) lParam
;
323 pContext
= (PCREATE_LINK_CONTEXT
) GetWindowLongPtr(hwndDlg
, DWLP_USER
);
324 if (lppsn
->hdr
.code
== PSN_WIZFINISH
)
328 GetDlgItemTextW(hwndDlg
, IDC_SHORTCUT_NAME
, pContext
->szDescription
, MAX_PATH
);
329 StrTrimW(pContext
->szDescription
, L
" \t");
331 /* if old shortcut file exists, then delete it now */
332 attrs
= GetFileAttributesW(pContext
->szOldFile
);
333 if (attrs
!= INVALID_FILE_ATTRIBUTES
&& !(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
335 DeleteFileW(pContext
->szOldFile
);
338 if (IsInternetLocation(pContext
->szTarget
))
341 StringCchCopyW(pContext
->szLinkName
, _countof(pContext
->szLinkName
),
343 PathAppendW(pContext
->szLinkName
, pContext
->szDescription
);
345 /* change extension if any */
346 pch
= PathFindExtensionW(pContext
->szLinkName
);
349 StringCchCatW(pContext
->szLinkName
, _countof(pContext
->szLinkName
), L
".url");
351 if (!CreateInternetShortcut(pContext
))
353 WCHAR szMessage
[128];
354 LoadStringW(hApplet
, IDS_CANTMAKEINETSHORTCUT
, szMessage
, _countof(szMessage
));
355 MessageBoxW(hwndDlg
, szMessage
, NULL
, MB_ICONERROR
);
361 StringCchCopyW(pContext
->szLinkName
, _countof(pContext
->szLinkName
),
363 PathAppendW(pContext
->szLinkName
, pContext
->szDescription
);
365 /* change extension if any */
366 pch
= PathFindExtensionW(pContext
->szLinkName
);
369 StringCchCatW(pContext
->szLinkName
, _countof(pContext
->szLinkName
), L
".lnk");
371 if (!CreateShortcut(pContext
))
373 WCHAR szMessage
[128];
374 LoadStringW(hApplet
, IDS_CANTMAKESHORTCUT
, szMessage
, _countof(szMessage
));
375 MessageBoxW(hwndDlg
, szMessage
, NULL
, MB_ICONERROR
);
385 ShowCreateShortcutWizard(HWND hwndCPl
, LPWSTR szPath
)
387 PROPSHEETHEADERW psh
;
388 HPROPSHEETPAGE ahpsp
[2];
394 PCREATE_LINK_CONTEXT pContext
= (PCREATE_LINK_CONTEXT
) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CREATE_LINK_CONTEXT
));
401 nLength
= wcslen(szPath
);
404 HeapFree(GetProcessHeap(), 0, pContext
);
406 /* no directory given */
410 attrs
= GetFileAttributesW(szPath
);
411 if (attrs
== INVALID_FILE_ATTRIBUTES
)
413 HeapFree(GetProcessHeap(), 0, pContext
);
419 /* build the pContext->szOrigin and pContext->szOldFile */
420 StringCchCopyW(pContext
->szOrigin
, _countof(pContext
->szOrigin
), szPath
);
421 pContext
->szOldFile
[0] = 0;
422 if (!(attrs
& FILE_ATTRIBUTE_DIRECTORY
))
425 StringCchCopyW(pContext
->szOldFile
, _countof(pContext
->szOldFile
), szPath
);
426 pch
= PathFindFileNameW(pContext
->szOrigin
);
430 PathAddBackslashW(pContext
->szOrigin
);
432 /* Create the Welcome page */
433 psp
.dwSize
= sizeof(PROPSHEETPAGE
);
434 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
435 psp
.hInstance
= hApplet
;
436 psp
.pfnDlgProc
= WelcomeDlgProc
;
437 psp
.pszTemplate
= MAKEINTRESOURCEW(IDD_SHORTCUT_LOCATION
);
438 psp
.lParam
= (LPARAM
)pContext
;
439 ahpsp
[nPages
++] = CreatePropertySheetPage(&psp
);
441 /* Create the Finish page */
442 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
443 psp
.pfnDlgProc
= FinishDlgProc
;
444 psp
.pszTemplate
= MAKEINTRESOURCEW(IDD_SHORTCUT_FINISH
);
445 ahpsp
[nPages
++] = CreatePropertySheetPage(&psp
);
448 /* Create the property sheet */
449 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
450 psh
.dwFlags
= PSH_WIZARD97
| PSH_WATERMARK
;
451 psh
.hInstance
= hApplet
;
452 psh
.hwndParent
= NULL
;
456 psh
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_SHORTCUT
);
458 /* Display the wizard */
460 HeapFree(GetProcessHeap(), 0, pContext
);
466 NewLinkHereW(HWND hwndCPl
, UINT uMsg
, LPARAM lParam1
, LPARAM lParam2
)
468 return ShowCreateShortcutWizard(hwndCPl
, (LPWSTR
) lParam1
);
473 NewLinkHereA(HWND hwndCPl
, UINT uMsg
, LPARAM lParam1
, LPARAM lParam2
)
475 WCHAR szFile
[MAX_PATH
];
477 if (MultiByteToWideChar(CP_ACP
, 0, (LPSTR
) lParam1
, -1, szFile
, MAX_PATH
))
479 return ShowCreateShortcutWizard(hwndCPl
, szFile
);