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