2004-08-15 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / lib / userenv / desktop.c
1 /* $Id: desktop.c,v 1.9 2004/08/15 19:02:40 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/userenv/desktop.c
6 * PURPOSE: Desktop and start menu support functions.
7 * PROGRAMMER: Eric Kohl
8 */
9
10 #include "precomp.h"
11 #include <shlobj.h>
12
13
14 /* FUNCTIONS ***************************************************************/
15
16 static BOOL
17 GetDesktopPath (BOOL bCommonPath,
18 LPWSTR lpDesktopPath)
19 {
20 WCHAR szPath[MAX_PATH];
21 DWORD dwLength;
22 DWORD dwType;
23 HKEY hKey;
24
25 DPRINT ("GetDesktopPath() called\n");
26
27 if (RegOpenKeyExW (HKEY_CURRENT_USER,
28 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
29 0,
30 KEY_ALL_ACCESS,
31 &hKey))
32 {
33 DPRINT1 ("RegOpenKeyExW() failed\n");
34 return FALSE;
35 }
36
37 dwLength = MAX_PATH * sizeof(WCHAR);
38 if (RegQueryValueExW (hKey,
39 bCommonPath ? L"Common Desktop" : L"Desktop",
40 0,
41 &dwType,
42 (LPBYTE)szPath,
43 &dwLength))
44 {
45 DPRINT1 ("RegQueryValueExW() failed\n");
46 RegCloseKey (hKey);
47 return FALSE;
48 }
49
50 RegCloseKey (hKey);
51
52 if (dwType == REG_EXPAND_SZ)
53 {
54 ExpandEnvironmentStringsW (szPath,
55 lpDesktopPath,
56 MAX_PATH);
57 }
58 else
59 {
60 wcscpy (lpDesktopPath, szPath);
61 }
62
63 DPRINT ("GetDesktopPath() done\n");
64
65 return TRUE;
66 }
67
68
69 static BOOL
70 GetProgramsPath (BOOL bCommonPath,
71 LPWSTR lpProgramsPath)
72 {
73 WCHAR szPath[MAX_PATH];
74 DWORD dwLength;
75 DWORD dwType;
76 HKEY hKey;
77
78 DPRINT ("GetProgramsPath() called\n");
79
80 if (RegOpenKeyExW (HKEY_CURRENT_USER,
81 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
82 0,
83 KEY_ALL_ACCESS,
84 &hKey))
85 {
86 DPRINT1 ("RegOpenKeyExW() failed\n");
87 return FALSE;
88 }
89
90 dwLength = MAX_PATH * sizeof(WCHAR);
91 if (RegQueryValueExW (hKey,
92 bCommonPath ? L"Common Programs" : L"Programs",
93 0,
94 &dwType,
95 (LPBYTE)szPath,
96 &dwLength))
97 {
98 DPRINT1 ("RegQueryValueExW() failed\n");
99 RegCloseKey (hKey);
100 return FALSE;
101 }
102
103 RegCloseKey (hKey);
104
105 if (dwType == REG_EXPAND_SZ)
106 {
107 ExpandEnvironmentStringsW (szPath,
108 lpProgramsPath,
109 MAX_PATH);
110 }
111 else
112 {
113 wcscpy (lpProgramsPath,
114 szPath);
115 }
116
117 DPRINT ("GetProgramsPath() done\n");
118
119 return TRUE;
120 }
121
122
123 BOOL WINAPI
124 AddDesktopItemA (BOOL bCommonItem,
125 LPCSTR lpItemName,
126 LPCSTR lpArguments,
127 LPCSTR lpIconLocation,
128 INT iIcon,
129 LPCSTR lpWorkingDirectory,
130 WORD wHotKey,
131 INT iShowCmd)
132 {
133 DPRINT1 ("AddDesktopItemA() not implemented!\n");
134 return FALSE;
135 }
136
137
138 BOOL WINAPI
139 AddDesktopItemW (BOOL bCommonDesktop,
140 LPCWSTR lpItemName,
141 LPCWSTR lpArguments,
142 LPCWSTR lpIconLocation,
143 INT iIcon,
144 LPCWSTR lpWorkingDirectory,
145 WORD wHotKey,
146 INT iShowCmd)
147 {
148 DYN_FUNCS Ole32;
149 WCHAR szLinkPath[MAX_PATH];
150 WCHAR szArguments[MAX_PATH];
151 WCHAR szCommand[MAX_PATH];
152 WIN32_FIND_DATA FindData;
153 HANDLE hFind;
154 LPWSTR Ptr;
155 DWORD dwLength;
156 IShellLinkW* psl;
157 IPersistFile* ppf;
158 HRESULT hr;
159 BOOL bResult;
160
161 DPRINT ("AddDesktopItemW() called\n");
162
163 bResult = FALSE;
164
165 if (!GetDesktopPath (bCommonDesktop, szLinkPath))
166 {
167 DPRINT1 ("GetDesktopPath() failed\n");
168 return FALSE;
169 }
170 DPRINT ("Desktop path: '%S'\n", szLinkPath);
171
172 /* Make sure the path exists */
173 hFind = FindFirstFileW (szLinkPath,
174 &FindData);
175 if (hFind == INVALID_HANDLE_VALUE)
176 {
177 DPRINT ("'%S' does not exist\n", szLinkPath);
178
179 /* Create directory path */
180 if (!CreateDirectoryPath (szLinkPath, NULL))
181 return FALSE;
182 }
183 else
184 {
185 DPRINT ("'%S' exists\n", szLinkPath);
186 FindClose (hFind);
187 }
188
189 /* Append backslash, item name and ".lnk" extension */
190 wcscat (szLinkPath, L"\\");
191 wcscat (szLinkPath, lpItemName);
192 wcscat (szLinkPath, L".lnk");
193 DPRINT ("Link path: '%S'\n", szLinkPath);
194
195 /* Split 'lpArguments' string into command and arguments */
196 Ptr = wcschr (lpArguments, L' ');
197 DPRINT ("Ptr %p lpArguments %p\n", Ptr, lpArguments);
198 if (Ptr != NULL)
199 {
200 dwLength = (DWORD)(Ptr - lpArguments);
201 DPRINT ("dwLength %lu\n", dwLength);
202 memcpy (szCommand, lpArguments, dwLength * sizeof(WCHAR));
203 szCommand[dwLength] = 0;
204 Ptr++;
205 wcscpy (szArguments, Ptr);
206 }
207 else
208 {
209 wcscpy (szCommand, lpArguments);
210 szArguments[0] = 0;
211 }
212 DPRINT ("szCommand: '%S'\n", szCommand);
213 DPRINT ("szArguments: '%S'\n", szArguments);
214
215 /* dynamically load ole32.dll */
216 if(!LoadDynamicImports(&DynOle32, &Ole32))
217 {
218 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
219 return FALSE;
220 }
221
222 Ole32.fn.CoInitialize(NULL);
223
224 hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink,
225 NULL,
226 CLSCTX_INPROC_SERVER,
227 &IID_IShellLinkW,
228 (LPVOID*)&psl);
229 if (!SUCCEEDED(hr))
230 {
231 Ole32.fn.CoUninitialize();
232 UnloadDynamicImports(&Ole32);
233 return FALSE;
234 }
235
236 hr = psl->lpVtbl->QueryInterface(psl,
237 &IID_IPersistFile,
238 (LPVOID*)&ppf);
239 if (SUCCEEDED(hr))
240 {
241 psl->lpVtbl->SetDescription(psl,
242 lpItemName);
243
244 psl->lpVtbl->SetPath(psl,
245 szCommand);
246
247 psl->lpVtbl->SetArguments(psl,
248 szArguments);
249
250 psl->lpVtbl->SetIconLocation(psl,
251 lpIconLocation,
252 iIcon);
253
254 if (lpWorkingDirectory != NULL)
255 {
256 psl->lpVtbl->SetWorkingDirectory(psl,
257 lpWorkingDirectory);
258 }
259 else
260 {
261 psl->lpVtbl->SetWorkingDirectory(psl,
262 L"%HOMEDRIVE%%HOMEPATH%");
263 }
264
265 psl->lpVtbl->SetHotkey(psl,
266 wHotKey);
267
268 psl->lpVtbl->SetShowCmd(psl,
269 iShowCmd);
270
271 hr = ppf->lpVtbl->Save(ppf,
272 szLinkPath,
273 TRUE);
274 if (SUCCEEDED(hr))
275 bResult = TRUE;
276
277 ppf->lpVtbl->Release(ppf);
278 }
279
280 psl->lpVtbl->Release(psl);
281
282 Ole32.fn.CoUninitialize();
283
284 UnloadDynamicImports(&Ole32);
285
286 DPRINT ("AddDesktopItemW() done\n");
287
288 return bResult;
289 }
290
291
292 BOOL WINAPI
293 DeleteDesktopItemA (BOOL bCommonItem,
294 LPCSTR lpItemName)
295 {
296 DPRINT1 ("DeleteDesktopItemA() not implemented!\n");
297 return FALSE;
298 }
299
300
301 BOOL WINAPI
302 DeleteDesktopItemW (BOOL bCommonItem,
303 LPCWSTR lpItemName)
304 {
305 WCHAR szLinkPath[MAX_PATH];
306
307 DPRINT ("DeleteDesktopItemW() called\n");
308
309 if (!GetDesktopPath (bCommonItem, szLinkPath))
310 {
311 DPRINT1 ("GetDesktopPath() failed\n");
312 return FALSE;
313 }
314
315 wcscat (szLinkPath, L"\\");
316 wcscat (szLinkPath, lpItemName);
317 wcscat (szLinkPath, L".lnk");
318 DPRINT ("Link path: '%S'\n", szLinkPath);
319
320 return DeleteFile (szLinkPath);
321 }
322
323
324 BOOL WINAPI
325 CreateGroupA (LPCSTR lpGroupName,
326 BOOL bCommonGroup)
327 {
328 DPRINT1 ("CreateGroupA() not implemented!\n");
329 return FALSE;
330 }
331
332
333 BOOL WINAPI
334 CreateGroupW (LPCWSTR lpGroupName,
335 BOOL bCommonGroup)
336 {
337 WCHAR szGroupPath[MAX_PATH];
338
339 DPRINT1 ("CreateGroupW() called\n");
340
341 if (lpGroupName == NULL || *lpGroupName == 0)
342 return TRUE;
343
344 if (!GetProgramsPath (bCommonGroup, szGroupPath))
345 {
346 DPRINT1 ("GetProgramsPath() failed\n");
347 return FALSE;
348 }
349 DPRINT1 ("Programs path: '%S'\n", szGroupPath);
350
351 wcscat (szGroupPath, L"\\");
352 wcscat (szGroupPath, lpGroupName);
353 DPRINT1 ("Group path: '%S'\n", szGroupPath);
354
355 /* Create directory path */
356 if (!CreateDirectoryPath (szGroupPath, NULL))
357 return FALSE;
358
359 /* FIXME: Notify the shell */
360
361 DPRINT1 ("CreateGroupW() done\n");
362
363 return TRUE;
364 }
365
366
367 BOOL WINAPI
368 DeleteGroupA (LPCSTR lpGroupName,
369 BOOL bCommonGroup)
370 {
371 DPRINT1 ("DeleteGroupA() not implemented!\n");
372 return FALSE;
373 }
374
375
376 BOOL WINAPI
377 DeleteGroupW (LPCWSTR lpGroupName,
378 BOOL bCommonGroup)
379 {
380 WCHAR szGroupPath[MAX_PATH];
381
382 DPRINT ("DeleteGroupW() called\n");
383
384 if (lpGroupName == NULL || *lpGroupName == 0)
385 return TRUE;
386
387 if (!GetProgramsPath (bCommonGroup, szGroupPath))
388 {
389 DPRINT1 ("GetProgramsPath() failed\n");
390 return FALSE;
391 }
392 DPRINT ("Programs path: '%S'\n", szGroupPath);
393
394 wcscat (szGroupPath, L"\\");
395 wcscat (szGroupPath, lpGroupName);
396 DPRINT ("Group path: '%S'\n", szGroupPath);
397
398 /* Remove directory path */
399 if (!RemoveDirectoryPath (szGroupPath))
400 return FALSE;
401
402 /* FIXME: Notify the shell */
403
404 DPRINT ("DeleteGroupW() done\n");
405
406 return TRUE;
407 }
408
409
410 BOOL WINAPI
411 AddItemA (LPCSTR lpGroupName,
412 BOOL bCommonGroup,
413 LPCSTR lpItemName,
414 LPCSTR lpArguments,
415 LPCSTR lpIconLocation,
416 INT iIcon,
417 LPCSTR lpWorkingDirectory,
418 WORD wHotKey,
419 INT iShowCmd)
420 {
421 DPRINT1 ("AddItemA() not implemented!\n");
422 return FALSE;
423 }
424
425
426 BOOL WINAPI
427 AddItemW (LPCWSTR lpGroupName,
428 BOOL bCommonGroup,
429 LPCWSTR lpItemName,
430 LPCWSTR lpArguments,
431 LPCWSTR lpIconLocation,
432 INT iIcon,
433 LPCWSTR lpWorkingDirectory,
434 WORD wHotKey,
435 INT iShowCmd)
436 {
437 DYN_FUNCS Ole32;
438 WCHAR szLinkPath[MAX_PATH];
439 WCHAR szArguments[MAX_PATH];
440 WCHAR szCommand[MAX_PATH];
441 WIN32_FIND_DATA FindData;
442 HANDLE hFind;
443 LPWSTR Ptr;
444 DWORD dwLength;
445 IShellLinkW* psl;
446 IPersistFile* ppf;
447 HRESULT hr;
448 BOOL bResult;
449
450 DPRINT ("AddItemW() called\n");
451
452 bResult = FALSE;
453
454 if (!GetProgramsPath (bCommonGroup, szLinkPath))
455 {
456 DPRINT1 ("GetProgramsPath() failed\n");
457 return FALSE;
458 }
459
460 DPRINT ("Programs path: '%S'\n", szLinkPath);
461
462 if (lpGroupName != NULL && *lpGroupName != 0)
463 {
464 wcscat (szLinkPath, L"\\");
465 wcscat (szLinkPath, lpGroupName);
466
467 /* Make sure the path exists */
468 hFind = FindFirstFileW (szLinkPath,
469 &FindData);
470 if (hFind == INVALID_HANDLE_VALUE)
471 {
472 DPRINT ("'%S' does not exist\n", szLinkPath);
473 if (!CreateGroupW (lpGroupName,
474 bCommonGroup))
475 return FALSE;
476 }
477 else
478 {
479 DPRINT ("'%S' exists\n", szLinkPath);
480 FindClose (hFind);
481 }
482 }
483
484 wcscat (szLinkPath, L"\\");
485 wcscat (szLinkPath, lpItemName);
486 wcscat (szLinkPath, L".lnk");
487 DPRINT ("Link path: '%S'\n", szLinkPath);
488
489 /* Split 'lpArguments' string into command and arguments */
490 Ptr = wcschr (lpArguments, L' ');
491 DPRINT ("Ptr %p lpArguments %p\n", Ptr, lpArguments);
492 if (Ptr != NULL)
493 {
494 dwLength = (DWORD)(Ptr - lpArguments);
495 DPRINT ("dwLength %lu\n", dwLength);
496 memcpy (szCommand, lpArguments, dwLength * sizeof(WCHAR));
497 szCommand[dwLength] = 0;
498 Ptr++;
499 wcscpy (szArguments, Ptr);
500 }
501 else
502 {
503 wcscpy (szCommand, lpArguments);
504 szArguments[0] = 0;
505 }
506 DPRINT ("szCommand: '%S'\n", szCommand);
507 DPRINT ("szArguments: '%S'\n", szArguments);
508
509 /* dynamically load ole32.dll */
510 if(!LoadDynamicImports(&DynOle32, &Ole32))
511 {
512 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
513 return FALSE;
514 }
515
516 Ole32.fn.CoInitialize(NULL);
517
518 hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink,
519 NULL,
520 CLSCTX_INPROC_SERVER,
521 &IID_IShellLinkW,
522 (LPVOID*)&psl);
523 if (!SUCCEEDED(hr))
524 {
525 Ole32.fn.CoUninitialize();
526 UnloadDynamicImports(&Ole32);
527 return FALSE;
528 }
529
530 hr = psl->lpVtbl->QueryInterface(psl,
531 &IID_IPersistFile,
532 (LPVOID*)&ppf);
533 if (SUCCEEDED(hr))
534 {
535 psl->lpVtbl->SetDescription(psl,
536 lpItemName);
537
538 psl->lpVtbl->SetPath(psl,
539 szCommand);
540
541 psl->lpVtbl->SetArguments(psl,
542 szArguments);
543
544 psl->lpVtbl->SetIconLocation(psl,
545 lpIconLocation,
546 iIcon);
547
548 if (lpWorkingDirectory != NULL)
549 {
550 psl->lpVtbl->SetWorkingDirectory(psl,
551 lpWorkingDirectory);
552 }
553 else
554 {
555 psl->lpVtbl->SetWorkingDirectory(psl,
556 L"%HOMEDRIVE%%HOMEPATH%");
557 }
558
559 psl->lpVtbl->SetHotkey(psl,
560 wHotKey);
561
562 psl->lpVtbl->SetShowCmd(psl,
563 iShowCmd);
564
565 hr = ppf->lpVtbl->Save(ppf,
566 szLinkPath,
567 TRUE);
568 if (SUCCEEDED(hr))
569 bResult = TRUE;
570
571 ppf->lpVtbl->Release(ppf);
572 }
573
574 psl->lpVtbl->Release(psl);
575
576 Ole32.fn.CoUninitialize();
577 UnloadDynamicImports(&Ole32);
578
579 DPRINT ("AddItemW() done\n");
580
581 return bResult;
582 }
583
584
585 BOOL WINAPI
586 DeleteItemA (LPCSTR lpGroupName,
587 BOOL bCommonGroup,
588 LPCSTR lpItemName,
589 BOOL bDeleteGroup)
590 {
591 DPRINT1 ("DeleteItemA() not implemented!\n");
592 return FALSE;
593 }
594
595
596 BOOL WINAPI
597 DeleteItemW (LPCWSTR lpGroupName,
598 BOOL bCommonGroup,
599 LPCWSTR lpItemName,
600 BOOL bDeleteGroup)
601 {
602 WCHAR szItemPath[MAX_PATH];
603 LPWSTR Ptr;
604
605 DPRINT ("DeleteItemW() called\n");
606
607 if (!GetProgramsPath (bCommonGroup, szItemPath))
608 {
609 DPRINT1 ("GetProgramsPath() failed\n");
610 return FALSE;
611 }
612 DPRINT ("Programs path: '%S'\n", szItemPath);
613
614 if (lpGroupName != NULL && *lpGroupName != 0)
615 {
616 wcscat (szItemPath, L"\\");
617 wcscat (szItemPath, lpGroupName);
618 }
619
620 wcscat (szItemPath, L"\\");
621 wcscat (szItemPath, lpItemName);
622 wcscat (szItemPath, L".lnk");
623 DPRINT ("Item path: '%S'\n", szItemPath);
624
625 if (!DeleteFileW (szItemPath))
626 return FALSE;
627
628 /* FIXME: Notify the shell */
629
630 if (bDeleteGroup)
631 {
632 Ptr = wcsrchr (szItemPath, L'\\');
633 if (Ptr == NULL)
634 return TRUE;
635
636 *Ptr = 0;
637 DPRINT ("Item path: '%S'\n", szItemPath);
638 if (RemoveDirectoryW (szItemPath))
639 {
640 /* FIXME: Notify the shell */
641 }
642 }
643
644 DPRINT ("DeleteItemW() done\n");
645
646 return TRUE;
647 }
648
649 /* EOF */