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)
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
= wcsrchr(pContext
->szTarget
, '.');
84 if (IsExtensionAShortcut(lpExtension
))
86 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_ALL
, &IID_IShellLinkW
, (void**)&pSourceShellLink
);
91 hr
= pSourceShellLink
->lpVtbl
->QueryInterface(pSourceShellLink
, &IID_IPersistFile
, (void**)&pPersistFile
);
94 pSourceShellLink
->lpVtbl
->Release(pSourceShellLink
);
98 hr
= pPersistFile
->lpVtbl
->Load(pPersistFile
, (LPCOLESTR
)pContext
->szTarget
, STGM_READ
);
99 pPersistFile
->lpVtbl
->Release(pPersistFile
);
103 pSourceShellLink
->lpVtbl
->Release(pSourceShellLink
);
107 hr
= pSourceShellLink
->lpVtbl
->GetPath(pSourceShellLink
, Path
, sizeof(Path
) / sizeof(WCHAR
), NULL
, 0);
108 pSourceShellLink
->lpVtbl
->Release(pSourceShellLink
);
117 wcscpy(Path
, pContext
->szTarget
);
120 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_ALL
,
121 &IID_IShellLinkW
, (void**)&pShellLink
);
127 pShellLink
->lpVtbl
->SetPath(pShellLink
, Path
);
128 pShellLink
->lpVtbl
->SetDescription(pShellLink
, pContext
->szDescription
);
129 pShellLink
->lpVtbl
->SetWorkingDirectory(pShellLink
, pContext
->szWorkingDirectory
);
131 hr
= pShellLink
->lpVtbl
->QueryInterface(pShellLink
, &IID_IPersistFile
, (void**)&pPersistFile
);
134 pShellLink
->lpVtbl
->Release(pShellLink
);
138 hr
= pPersistFile
->lpVtbl
->Save(pPersistFile
, pContext
->szLinkName
, TRUE
);
139 pPersistFile
->lpVtbl
->Release(pPersistFile
);
140 pShellLink
->lpVtbl
->Release(pShellLink
);
149 WelcomeDlgProc(HWND hwndDlg
,
154 LPPROPSHEETPAGEW ppsp
;
155 PCREATE_LINK_CONTEXT pContext
;
157 WCHAR szPath
[MAX_PATH
];
160 LPITEMIDLIST pidllist
;
166 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
167 pContext
= (PCREATE_LINK_CONTEXT
) ppsp
->lParam
;
168 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pContext
);
169 PropSheet_SetWizButtons(GetParent(hwndDlg
), 0);
172 switch(HIWORD(wParam
))
175 if (SendDlgItemMessage(hwndDlg
, IDC_SHORTCUT_LOCATION
, WM_GETTEXTLENGTH
, 0, 0))
177 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
);
181 PropSheet_SetWizButtons(GetParent(hwndDlg
), 0);
185 switch(LOWORD(wParam
))
187 case IDC_SHORTCUT_BROWSE
:
188 ZeroMemory(&brws
, sizeof(brws
));
189 brws
.hwndOwner
= hwndDlg
;
190 brws
.pidlRoot
= NULL
;
191 brws
.pszDisplayName
= szPath
;
192 brws
.ulFlags
= BIF_BROWSEINCLUDEFILES
;
194 pidllist
= SHBrowseForFolderW(&brws
);
198 if (SHGetPathFromIDListW(pidllist
, szPath
))
199 SendDlgItemMessage(hwndDlg
, IDC_SHORTCUT_LOCATION
, WM_SETTEXT
, 0, (LPARAM
)szPath
);
201 /* Free memory, if possible */
202 if (SUCCEEDED(SHGetMalloc(&malloc
)))
204 IMalloc_Free(malloc
, pidllist
);
205 IMalloc_Release(malloc
);
212 lppsn
= (LPPSHNOTIFY
) lParam
;
213 if (lppsn
->hdr
.code
== PSN_WIZNEXT
)
215 pContext
= (PCREATE_LINK_CONTEXT
) GetWindowLongPtr(hwndDlg
, DWLP_USER
);
216 SendDlgItemMessageW(hwndDlg
, IDC_SHORTCUT_LOCATION
, WM_GETTEXT
, MAX_PATH
, (LPARAM
)pContext
->szTarget
);
219 /// it should also be possible to create a link to folders, shellobjects etc....
221 if (GetFileAttributesW(pContext
->szTarget
) == INVALID_FILE_ATTRIBUTES
)
225 if (LoadStringW(hApplet
, IDS_CREATE_SHORTCUT
, szDesc
, 100) < 100 &&
226 LoadStringW(hApplet
, IDS_ERROR_NOT_FOUND
, szPath
, MAX_PATH
) < MAX_PATH
)
228 WCHAR szError
[MAX_PATH
+ 100];
229 swprintf(szError
, szPath
, pContext
->szTarget
);
230 MessageBoxW(hwndDlg
, szError
, szDesc
, MB_ICONERROR
);
232 SendDlgItemMessage(hwndDlg
, IDC_SHORTCUT_LOCATION
, EM_SETSEL
, 0, -1);
233 SetFocus(GetDlgItem(hwndDlg
, IDC_SHORTCUT_LOCATION
));
234 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, PSNRET_INVALID_NOCHANGEPAGE
);
239 WCHAR
* first
, *last
;
240 wcscpy(pContext
->szWorkingDirectory
, pContext
->szTarget
);
241 first
= wcschr(pContext
->szWorkingDirectory
, L
'\\');
242 last
= wcsrchr(pContext
->szWorkingDirectory
, L
'\\');
243 wcscpy(pContext
->szDescription
, &last
[1]);
250 first
= wcsrchr(pContext
->szDescription
, L
'.');
264 FinishDlgProc(HWND hwndDlg
,
269 LPPROPSHEETPAGEW ppsp
;
270 PCREATE_LINK_CONTEXT pContext
;
276 ppsp
= (LPPROPSHEETPAGEW
)lParam
;
277 pContext
= (PCREATE_LINK_CONTEXT
) ppsp
->lParam
;
278 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pContext
);
279 SendDlgItemMessageW(hwndDlg
, IDC_SHORTCUT_NAME
, WM_SETTEXT
, 0, (LPARAM
)pContext
->szDescription
);
280 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_FINISH
);
283 switch(HIWORD(wParam
))
286 if (SendDlgItemMessage(hwndDlg
, IDC_SHORTCUT_NAME
, WM_GETTEXTLENGTH
, 0, 0))
288 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_FINISH
);
292 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
);
298 lppsn
= (LPPSHNOTIFY
) lParam
;
299 pContext
= (PCREATE_LINK_CONTEXT
) GetWindowLongPtr(hwndDlg
, DWLP_USER
);
300 if (lppsn
->hdr
.code
== PSN_WIZFINISH
)
302 SendDlgItemMessageW(hwndDlg
, IDC_SHORTCUT_NAME
, WM_GETTEXT
, MAX_PATH
, (LPARAM
)pContext
->szDescription
);
303 wcscat(pContext
->szLinkName
, pContext
->szDescription
);
304 wcscat(pContext
->szLinkName
, L
".lnk");
305 if (!CreateShortcut(pContext
))
307 MessageBox(hwndDlg
, _T("Failed to create shortcut"), _T("Error"), MB_ICONERROR
);
317 ShowCreateShortcutWizard(HWND hwndCPl
, LPWSTR szPath
)
319 PROPSHEETHEADERW psh
;
320 HPROPSHEETPAGE ahpsp
[2];
326 PCREATE_LINK_CONTEXT pContext
= (PCREATE_LINK_CONTEXT
) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CREATE_LINK_CONTEXT
));
332 nLength
= wcslen(szPath
);
335 HeapFree(GetProcessHeap(), 0, pContext
);
337 /* no directory given */
341 attrs
= GetFileAttributesW(szPath
);
342 if (attrs
== INVALID_FILE_ATTRIBUTES
)
344 HeapFree(GetProcessHeap(), 0, pContext
);
350 wcscpy(pContext
->szLinkName
, szPath
);
351 if (pContext
->szLinkName
[nLength
-1] != L
'\\')
353 pContext
->szLinkName
[nLength
] = L
'\\';
354 pContext
->szLinkName
[nLength
+1] = L
'\0';
358 /* Create the Welcome page */
359 psp
.dwSize
= sizeof(PROPSHEETPAGE
);
360 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
361 psp
.hInstance
= hApplet
;
362 psp
.pfnDlgProc
= WelcomeDlgProc
;
363 psp
.pszTemplate
= MAKEINTRESOURCEW(IDD_SHORTCUT_LOCATION
);
364 psp
.lParam
= (LPARAM
)pContext
;
365 ahpsp
[nPages
++] = CreatePropertySheetPage(&psp
);
367 /* Create the Finish page */
368 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
369 psp
.pfnDlgProc
= FinishDlgProc
;
370 psp
.pszTemplate
= MAKEINTRESOURCEW(IDD_SHORTCUT_FINISH
);
371 ahpsp
[nPages
++] = CreatePropertySheetPage(&psp
);
374 /* Create the property sheet */
375 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
376 psh
.dwFlags
= PSH_WIZARD97
| PSH_WATERMARK
;
377 psh
.hInstance
= hApplet
;
378 psh
.hwndParent
= NULL
;
382 psh
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_SHORTCUT
);
384 /* Display the wizard */
386 HeapFree(GetProcessHeap(), 0, pContext
);
392 NewLinkHereW(HWND hwndCPl
, UINT uMsg
, LPARAM lParam1
, LPARAM lParam2
)
394 return ShowCreateShortcutWizard(hwndCPl
, (LPWSTR
) lParam1
);
399 NewLinkHereA(HWND hwndCPl
, UINT uMsg
, LPARAM lParam1
, LPARAM lParam2
)
401 WCHAR szFile
[MAX_PATH
];
403 if (MultiByteToWideChar(CP_ACP
, 0, (LPSTR
) lParam1
, -1, szFile
, MAX_PATH
))
405 return ShowCreateShortcutWizard(hwndCPl
, szFile
);