Sync to trunk head (35333)
[reactos.git] / reactos / dll / cpl / appwiz / createlink.c
1 /* $Id: appwiz.c 29364 2007-10-02 23:34:00Z janderwald $
2 *
3 * PROJECT: ReactOS Software Control Panel
4 * FILE: dll/cpl/appwiz/createlink.c
5 * PURPOSE: ReactOS Software Control Panel
6 * PROGRAMMER: Gero Kuehn (reactos.filter@gkware.com)
7 * Dmitry Chapyshev (lentind@yandex.ru)
8 * Johannes Anderwald
9 * UPDATE HISTORY:
10 * 06-17-2004 Created
11 */
12
13 #include "appwiz.h"
14
15
16 BOOL
17 CreateShortcut(PCREATE_LINK_CONTEXT pContext)
18 {
19 IShellLinkW *pShellLink;
20 IPersistFile *pPersistFile;
21 HRESULT hr;
22
23 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_ALL,
24 &IID_IShellLink, (void**)&pShellLink);
25
26 if (hr != S_OK)
27 return FALSE;
28
29
30 pShellLink->lpVtbl->SetPath(pShellLink, pContext->szTarget);
31 pShellLink->lpVtbl->SetDescription(pShellLink, pContext->szDescription);
32 pShellLink->lpVtbl->SetWorkingDirectory(pShellLink, pContext->szWorkingDirectory);
33
34 hr = pShellLink->lpVtbl->QueryInterface(pShellLink, &IID_IPersistFile, (void**)&pPersistFile);
35 if (hr != S_OK)
36 {
37 pShellLink->lpVtbl->Release(pShellLink);
38 return FALSE;
39 }
40
41 hr = pPersistFile->lpVtbl->Save(pPersistFile, pContext->szLinkName, TRUE);
42 pPersistFile->lpVtbl->Release(pPersistFile);
43 pShellLink->lpVtbl->Release(pShellLink);
44 return (hr == S_OK);
45 }
46
47
48
49
50 INT_PTR
51 CALLBACK
52 WelcomeDlgProc(HWND hwndDlg,
53 UINT uMsg,
54 WPARAM wParam,
55 LPARAM lParam)
56 {
57 LPPROPSHEETPAGEW ppsp;
58 PCREATE_LINK_CONTEXT pContext;
59 LPPSHNOTIFY lppsn;
60 WCHAR szPath[MAX_PATH];
61 WCHAR szDesc[100];
62 BROWSEINFOW brws;
63 LPITEMIDLIST pidllist;
64 IMalloc* malloc;
65
66 switch(uMsg)
67 {
68 case WM_INITDIALOG:
69 ppsp = (LPPROPSHEETPAGEW)lParam;
70 pContext = (PCREATE_LINK_CONTEXT) ppsp->lParam;
71 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
72 PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
73 break;
74 case WM_COMMAND:
75 switch(HIWORD(wParam))
76 {
77 case EN_CHANGE:
78 if (SendDlgItemMessage(hwndDlg, IDC_SHORTCUT_LOCATION, WM_GETTEXTLENGTH, 0, 0))
79 {
80 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
81 }
82 else
83 {
84 PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
85 }
86 break;
87 }
88 switch(LOWORD(wParam))
89 {
90 case IDC_SHORTCUT_BROWSE:
91 ZeroMemory(&brws, sizeof(brws));
92 brws.hwndOwner = hwndDlg;
93 brws.pidlRoot = NULL;
94 brws.pszDisplayName = szPath;
95 brws.ulFlags = BIF_BROWSEINCLUDEFILES;
96 brws.lpfn = NULL;
97 pidllist = SHBrowseForFolder(&brws);
98 if (!pidllist)
99 break;
100
101 if (SHGetPathFromIDList(pidllist, szPath))
102 SendDlgItemMessage(hwndDlg, IDC_SHORTCUT_LOCATION, WM_SETTEXT, 0, (LPARAM)szPath);
103
104 /* Free memory, if possible */
105 if (SUCCEEDED(SHGetMalloc(&malloc)))
106 {
107 IMalloc_Free(malloc, pidllist);
108 IMalloc_Release(malloc);
109 }
110
111 break;
112 }
113 break;
114 case WM_NOTIFY:
115 lppsn = (LPPSHNOTIFY) lParam;
116 if (lppsn->hdr.code == PSN_WIZNEXT)
117 {
118 pContext = (PCREATE_LINK_CONTEXT) GetWindowLongPtr(hwndDlg, DWLP_USER);
119 SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_LOCATION, WM_GETTEXT, MAX_PATH, (LPARAM)pContext->szTarget);
120 ///
121 /// FIXME
122 /// it should also be possible to create a link to folders, shellobjects etc....
123 ///
124 if (GetFileAttributesW(pContext->szTarget) == INVALID_FILE_ATTRIBUTES)
125 {
126 szDesc[0] = L'\0';
127 szPath[0] = L'\0';
128 if (LoadStringW(hApplet, IDS_CREATE_SHORTCUT, szDesc, 100) < 100 &&
129 LoadStringW(hApplet, IDS_ERROR_NOT_FOUND, szPath, MAX_PATH) < MAX_PATH)
130 {
131 WCHAR szError[MAX_PATH + 100];
132 #ifdef _MSC_VER
133 _swprintf(szError, szPath, pContext->szTarget);
134 #else
135 swprintf(szError, szPath, pContext->szTarget);
136 #endif
137 MessageBoxW(hwndDlg, szError, szDesc, MB_ICONERROR);
138 }
139 SendDlgItemMessage(hwndDlg, IDC_SHORTCUT_LOCATION, EM_SETSEL, 0, -1);
140 SetFocus(GetDlgItem(hwndDlg, IDC_SHORTCUT_LOCATION));
141 SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
142 return -1;
143 }
144 else
145 {
146 WCHAR * first, *last;
147 wcscpy(pContext->szWorkingDirectory, pContext->szTarget);
148 first = wcschr(pContext->szWorkingDirectory, L'\\');
149 last = wcsrchr(pContext->szWorkingDirectory, L'\\');
150 wcscpy(pContext->szDescription, &last[1]);
151
152 if (first != last)
153 last[0] = L'\0';
154 else
155 first[1] = L'\0';
156
157 first = wcsrchr(pContext->szDescription, L'.');
158 first[0] = L'\0';
159 }
160
161 }
162 break;
163 }
164 return FALSE;
165 }
166
167 INT_PTR
168 CALLBACK
169 FinishDlgProc(HWND hwndDlg,
170 UINT uMsg,
171 WPARAM wParam,
172 LPARAM lParam)
173 {
174 LPPROPSHEETPAGEW ppsp;
175 PCREATE_LINK_CONTEXT pContext;
176 LPPSHNOTIFY lppsn;
177
178 switch(uMsg)
179 {
180 case WM_INITDIALOG:
181 ppsp = (LPPROPSHEETPAGEW)lParam;
182 pContext = (PCREATE_LINK_CONTEXT) ppsp->lParam;
183 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
184 SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_NAME, WM_SETTEXT, 0, (LPARAM)pContext->szDescription);
185 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH);
186 break;
187 case WM_COMMAND:
188 switch(HIWORD(wParam))
189 {
190 case EN_CHANGE:
191 if (SendDlgItemMessage(hwndDlg, IDC_SHORTCUT_NAME, WM_GETTEXTLENGTH, 0, 0))
192 {
193 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH);
194 }
195 else
196 {
197 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
198 }
199 break;
200 }
201 break;
202 case WM_NOTIFY:
203 lppsn = (LPPSHNOTIFY) lParam;
204 pContext = (PCREATE_LINK_CONTEXT) GetWindowLongPtr(hwndDlg, DWLP_USER);
205 if (lppsn->hdr.code == PSN_WIZFINISH)
206 {
207 SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_NAME, WM_GETTEXT, MAX_PATH, (LPARAM)pContext->szDescription);
208 wcscat(pContext->szLinkName, pContext->szDescription);
209 wcscat(pContext->szLinkName, L".lnk");
210 if (!CreateShortcut(pContext))
211 {
212 MessageBox(hwndDlg, _T("Failed to create shortcut"), _T("Error"), MB_ICONERROR);
213 }
214 }
215
216
217 }
218 return FALSE;
219 }
220
221 LONG CALLBACK
222 ShowCreateShortcutWizard(HWND hwndCPl, LPWSTR szPath)
223 {
224 PROPSHEETHEADERW psh;
225 HPROPSHEETPAGE ahpsp[2];
226 PROPSHEETPAGE psp;
227 UINT nPages = 0;
228 UINT nLength;
229
230 PCREATE_LINK_CONTEXT pContext = (PCREATE_LINK_CONTEXT) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CREATE_LINK_CONTEXT));
231 if (!pContext)
232 {
233 /* no memory */
234 return FALSE;
235 }
236 nLength = wcslen(szPath);
237 if (!nLength)
238 {
239 /* no directory given */
240 return FALSE;
241 }
242 ///
243 /// FIXME
244 /// check if path is valid
245 ///
246
247 wcscpy(pContext->szLinkName, szPath);
248 if (pContext->szLinkName[nLength-1] != L'\\')
249 {
250 pContext->szLinkName[nLength] = L'\\';
251 pContext->szLinkName[nLength+1] = L'\0';
252 }
253
254
255 /* Create the Welcome page */
256 psp.dwSize = sizeof(PROPSHEETPAGE);
257 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
258 psp.hInstance = hApplet;
259 psp.pfnDlgProc = WelcomeDlgProc;
260 psp.pszTemplate = MAKEINTRESOURCE(IDD_SHORTCUT_LOCATION);
261 psp.lParam = (LPARAM)pContext;
262 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
263
264 /* Create the Finish page */
265 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
266 psp.pfnDlgProc = FinishDlgProc;
267 psp.pszTemplate = MAKEINTRESOURCE(IDD_SHORTCUT_FINISH);
268 ahpsp[nPages++] = CreatePropertySheetPage(&psp);
269
270
271 /* Create the property sheet */
272 psh.dwSize = sizeof(PROPSHEETHEADER);
273 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK;
274 psh.hInstance = hApplet;
275 psh.hwndParent = NULL;
276 psh.nPages = nPages;
277 psh.nStartPage = 0;
278 psh.phpage = ahpsp;
279 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
280
281 /* Display the wizard */
282 PropertySheet(&psh);
283 HeapFree(GetProcessHeap(), 0, pContext);
284 return TRUE;
285 }
286
287
288 LONG
289 CALLBACK
290 NewLinkHere(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
291 {
292 WCHAR szFile[MAX_PATH];
293
294 if (MultiByteToWideChar(CP_ACP, 0, (char*)lParam1, strlen((char*)lParam1)+1, szFile, MAX_PATH))
295 {
296 return ShowCreateShortcutWizard(hwndCPl, szFile);
297 }
298 return -1;
299 }
300
301
302 LONG
303 CALLBACK
304 NewLinkHereW(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
305 {
306 return ShowCreateShortcutWizard(hwndCPl, (LPWSTR)lParam1);
307 }
308
309 LONG
310 CALLBACK
311 NewLinkHereA(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
312 {
313 WCHAR szFile[MAX_PATH];
314
315 if (MultiByteToWideChar(CP_ACP, 0, (char*)lParam1, strlen((char*)lParam1)+1, szFile, MAX_PATH))
316 {
317 return ShowCreateShortcutWizard(hwndCPl, szFile);
318 }
319 return -1;
320 }