[USERENV][USER32]
[reactos.git] / reactos / dll / win32 / userenv / desktop.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * FILE: lib/userenv/desktop.c
23 * PURPOSE: Desktop and start menu support functions.
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include "precomp.h"
28
29 #define NDEBUG
30 #include <debug.h>
31
32
33 /* FUNCTIONS ***************************************************************/
34
35 static BOOL
36 GetDesktopPath (BOOL bCommonPath,
37 LPWSTR lpDesktopPath)
38 {
39 WCHAR szPath[MAX_PATH];
40 DWORD dwLength;
41 DWORD dwType;
42 HKEY hKey;
43 LONG Error;
44
45 DPRINT ("GetDesktopPath() called\n");
46
47 Error = RegOpenKeyExW (HKEY_CURRENT_USER,
48 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
49 0,
50 KEY_QUERY_VALUE,
51 &hKey);
52 if (Error != ERROR_SUCCESS)
53 {
54 DPRINT1 ("RegOpenKeyExW() failed\n");
55 SetLastError((DWORD)Error);
56 return FALSE;
57 }
58
59 dwLength = MAX_PATH * sizeof(WCHAR);
60 Error = RegQueryValueExW (hKey,
61 bCommonPath ? L"Common Desktop" : L"Desktop",
62 0,
63 &dwType,
64 (LPBYTE)szPath,
65 &dwLength);
66 if (Error != ERROR_SUCCESS)
67 {
68 DPRINT1 ("RegQueryValueExW() failed\n");
69 RegCloseKey (hKey);
70 SetLastError((DWORD)Error);
71 return FALSE;
72 }
73
74 RegCloseKey (hKey);
75
76 if (dwType == REG_EXPAND_SZ)
77 {
78 ExpandEnvironmentStringsW (szPath,
79 lpDesktopPath,
80 MAX_PATH);
81 }
82 else
83 {
84 wcscpy (lpDesktopPath, szPath);
85 }
86
87 DPRINT ("GetDesktopPath() done\n");
88
89 return TRUE;
90 }
91
92
93 static BOOL
94 GetProgramsPath (BOOL bCommonPath,
95 LPWSTR lpProgramsPath)
96 {
97 WCHAR szPath[MAX_PATH];
98 DWORD dwLength;
99 DWORD dwType;
100 HKEY hKey;
101 LONG Error;
102
103 DPRINT ("GetProgramsPath() called\n");
104
105 Error = RegOpenKeyExW (HKEY_CURRENT_USER,
106 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
107 0,
108 KEY_QUERY_VALUE,
109 &hKey);
110 if (Error != ERROR_SUCCESS)
111 {
112 DPRINT1 ("RegOpenKeyExW() failed\n");
113 SetLastError((DWORD)Error);
114 return FALSE;
115 }
116
117 dwLength = MAX_PATH * sizeof(WCHAR);
118 Error = RegQueryValueExW (hKey,
119 bCommonPath ? L"Common Programs" : L"Programs",
120 0,
121 &dwType,
122 (LPBYTE)szPath,
123 &dwLength);
124 if (Error != ERROR_SUCCESS)
125 {
126 DPRINT1 ("RegQueryValueExW() failed\n");
127 RegCloseKey (hKey);
128 SetLastError((DWORD)Error);
129 return FALSE;
130 }
131
132 RegCloseKey (hKey);
133
134 if (dwType == REG_EXPAND_SZ)
135 {
136 ExpandEnvironmentStringsW (szPath,
137 lpProgramsPath,
138 MAX_PATH);
139 }
140 else
141 {
142 wcscpy (lpProgramsPath,
143 szPath);
144 }
145
146 DPRINT ("GetProgramsPath() done\n");
147
148 return TRUE;
149 }
150
151
152 BOOL WINAPI
153 AddDesktopItemA (BOOL bCommonItem,
154 LPCSTR lpItemName,
155 LPCSTR lpArguments,
156 LPCSTR lpIconLocation,
157 INT iIcon,
158 LPCSTR lpWorkingDirectory, /* Optional */
159 WORD wHotKey,
160 INT iShowCmd)
161 {
162 UNICODE_STRING ItemName;
163 UNICODE_STRING Arguments;
164 UNICODE_STRING IconLocation;
165 UNICODE_STRING WorkingDirectory;
166 BOOL bResult;
167
168 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName,
169 (LPSTR)lpItemName))
170 {
171 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
172 return FALSE;
173 }
174
175 if (!RtlCreateUnicodeStringFromAsciiz(&Arguments,
176 (LPSTR)lpArguments))
177 {
178 RtlFreeUnicodeString(&ItemName);
179 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
180 return FALSE;
181 }
182
183 if (!RtlCreateUnicodeStringFromAsciiz(&IconLocation,
184 (LPSTR)lpIconLocation))
185 {
186 RtlFreeUnicodeString(&Arguments);
187 RtlFreeUnicodeString(&ItemName);
188 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
189 return FALSE;
190 }
191
192 if (lpWorkingDirectory != NULL)
193 {
194 if (!RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory,
195 (LPSTR)lpWorkingDirectory))
196 {
197 RtlFreeUnicodeString(&IconLocation);
198 RtlFreeUnicodeString(&Arguments);
199 RtlFreeUnicodeString(&ItemName);
200 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
201 return FALSE;
202 }
203 }
204
205 bResult = AddDesktopItemW(bCommonItem,
206 ItemName.Buffer,
207 Arguments.Buffer,
208 IconLocation.Buffer,
209 iIcon,
210 (lpWorkingDirectory != NULL) ? WorkingDirectory.Buffer : NULL,
211 wHotKey,
212 iShowCmd);
213
214 if (lpWorkingDirectory != NULL)
215 {
216 RtlFreeUnicodeString(&WorkingDirectory);
217 }
218
219 RtlFreeUnicodeString(&IconLocation);
220 RtlFreeUnicodeString(&Arguments);
221 RtlFreeUnicodeString(&ItemName);
222
223 return bResult;
224 }
225
226
227 BOOL WINAPI
228 AddDesktopItemW (BOOL bCommonDesktop,
229 LPCWSTR lpItemName,
230 LPCWSTR lpArguments,
231 LPCWSTR lpIconLocation,
232 INT iIcon,
233 LPCWSTR lpWorkingDirectory, /* Optional */
234 WORD wHotKey,
235 INT iShowCmd)
236 {
237 DYN_FUNCS Ole32;
238 WCHAR szLinkPath[MAX_PATH];
239 WCHAR szArguments[MAX_PATH];
240 WCHAR szCommand[MAX_PATH];
241 WIN32_FIND_DATAW FindData;
242 HANDLE hFind;
243 LPWSTR Ptr;
244 DWORD dwLength;
245 IShellLinkW* psl;
246 IPersistFile* ppf;
247 HRESULT hr;
248 BOOL bResult;
249
250 DPRINT ("AddDesktopItemW() called\n");
251
252 bResult = FALSE;
253
254 if (!GetDesktopPath (bCommonDesktop, szLinkPath))
255 {
256 DPRINT1 ("GetDesktopPath() failed\n");
257 return FALSE;
258 }
259 DPRINT ("Desktop path: '%S'\n", szLinkPath);
260
261 /* Make sure the path exists */
262 hFind = FindFirstFileW (szLinkPath,
263 &FindData);
264 if (hFind == INVALID_HANDLE_VALUE)
265 {
266 DPRINT ("'%S' does not exist\n", szLinkPath);
267
268 /* Create directory path */
269 if (!CreateDirectoryPath (szLinkPath, NULL))
270 return FALSE;
271 }
272 else
273 {
274 DPRINT ("'%S' exists\n", szLinkPath);
275 FindClose (hFind);
276 }
277
278 /* Append backslash, item name and ".lnk" extension */
279 wcscat (szLinkPath, L"\\");
280 wcscat (szLinkPath, lpItemName);
281 wcscat (szLinkPath, L".lnk");
282 DPRINT ("Link path: '%S'\n", szLinkPath);
283
284 /* Split 'lpArguments' string into command and arguments */
285 Ptr = wcschr (lpArguments, L' ');
286 DPRINT ("Ptr %p lpArguments %p\n", Ptr, lpArguments);
287 if (Ptr != NULL)
288 {
289 dwLength = (DWORD)(Ptr - lpArguments);
290 DPRINT ("dwLength %lu\n", dwLength);
291 memcpy (szCommand, lpArguments, dwLength * sizeof(WCHAR));
292 szCommand[dwLength] = 0;
293 Ptr++;
294 wcscpy (szArguments, Ptr);
295 }
296 else
297 {
298 wcscpy (szCommand, lpArguments);
299 szArguments[0] = 0;
300 }
301 DPRINT ("szCommand: '%S'\n", szCommand);
302 DPRINT ("szArguments: '%S'\n", szArguments);
303
304 /* Dynamically load ole32.dll */
305 if (!LoadDynamicImports(&DynOle32, &Ole32))
306 {
307 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
308 return FALSE;
309 }
310
311 Ole32.fn.CoInitialize(NULL);
312
313 hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink,
314 NULL,
315 CLSCTX_INPROC_SERVER,
316 &IID_IShellLinkW,
317 (LPVOID*)&psl);
318 if (!SUCCEEDED(hr))
319 {
320 Ole32.fn.CoUninitialize();
321 UnloadDynamicImports(&Ole32);
322 return FALSE;
323 }
324
325 hr = psl->lpVtbl->QueryInterface(psl,
326 &IID_IPersistFile,
327 (LPVOID*)&ppf);
328 if (SUCCEEDED(hr))
329 {
330 psl->lpVtbl->SetDescription(psl,
331 lpItemName);
332
333 psl->lpVtbl->SetPath(psl,
334 szCommand);
335
336 psl->lpVtbl->SetArguments(psl,
337 szArguments);
338
339 psl->lpVtbl->SetIconLocation(psl,
340 lpIconLocation,
341 iIcon);
342
343 if (lpWorkingDirectory != NULL)
344 {
345 psl->lpVtbl->SetWorkingDirectory(psl,
346 lpWorkingDirectory);
347 }
348 else
349 {
350 psl->lpVtbl->SetWorkingDirectory(psl,
351 L"%HOMEDRIVE%%HOMEPATH%");
352 }
353
354 psl->lpVtbl->SetHotkey(psl,
355 wHotKey);
356
357 psl->lpVtbl->SetShowCmd(psl,
358 iShowCmd);
359
360 hr = ppf->lpVtbl->Save(ppf,
361 szLinkPath,
362 TRUE);
363 if (SUCCEEDED(hr))
364 bResult = TRUE;
365
366 ppf->lpVtbl->Release(ppf);
367 }
368
369 psl->lpVtbl->Release(psl);
370
371 Ole32.fn.CoUninitialize();
372
373 UnloadDynamicImports(&Ole32);
374
375 DPRINT ("AddDesktopItemW() done\n");
376
377 return bResult;
378 }
379
380
381 BOOL WINAPI
382 DeleteDesktopItemA (BOOL bCommonItem,
383 LPCSTR lpItemName)
384 {
385 UNICODE_STRING ItemName;
386 BOOL bResult;
387
388 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName,
389 (LPSTR)lpItemName))
390 {
391 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
392 return FALSE;
393 }
394
395 bResult = DeleteDesktopItemW(bCommonItem,
396 ItemName.Buffer);
397
398 RtlFreeUnicodeString(&ItemName);
399
400 return bResult;
401 }
402
403
404 BOOL WINAPI
405 DeleteDesktopItemW (BOOL bCommonItem,
406 LPCWSTR lpItemName)
407 {
408 WCHAR szLinkPath[MAX_PATH];
409
410 DPRINT ("DeleteDesktopItemW() called\n");
411
412 if (!GetDesktopPath (bCommonItem, szLinkPath))
413 {
414 DPRINT1 ("GetDesktopPath() failed\n");
415 return FALSE;
416 }
417
418 wcscat (szLinkPath, L"\\");
419 wcscat (szLinkPath, lpItemName);
420 wcscat (szLinkPath, L".lnk");
421 DPRINT ("Link path: '%S'\n", szLinkPath);
422
423 return DeleteFileW (szLinkPath);
424 }
425
426
427 BOOL WINAPI
428 CreateGroupA (LPCSTR lpGroupName,
429 BOOL bCommonGroup)
430 {
431 UNICODE_STRING GroupName;
432 BOOL bResult;
433
434 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName,
435 (LPSTR)lpGroupName))
436 {
437 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
438 return FALSE;
439 }
440
441 bResult = CreateGroupW(GroupName.Buffer, bCommonGroup);
442
443 RtlFreeUnicodeString(&GroupName);
444
445 return bResult;
446 }
447
448
449 BOOL WINAPI
450 CreateGroupW (LPCWSTR lpGroupName,
451 BOOL bCommonGroup)
452 {
453 WCHAR szGroupPath[MAX_PATH];
454
455 DPRINT1 ("CreateGroupW() called\n");
456
457 if (lpGroupName == NULL || *lpGroupName == 0)
458 return TRUE;
459
460 if (!GetProgramsPath (bCommonGroup, szGroupPath))
461 {
462 DPRINT1 ("GetProgramsPath() failed\n");
463 return FALSE;
464 }
465 DPRINT1 ("Programs path: '%S'\n", szGroupPath);
466
467 wcscat (szGroupPath, L"\\");
468 wcscat (szGroupPath, lpGroupName);
469 DPRINT1 ("Group path: '%S'\n", szGroupPath);
470
471 /* Create directory path */
472 if (!CreateDirectoryPath (szGroupPath, NULL))
473 return FALSE;
474
475 /* FIXME: Notify the shell */
476
477 DPRINT1 ("CreateGroupW() done\n");
478
479 return TRUE;
480 }
481
482
483 BOOL WINAPI
484 DeleteGroupA (LPCSTR lpGroupName,
485 BOOL bCommonGroup)
486 {
487 UNICODE_STRING GroupName;
488 BOOL bResult;
489
490 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName,
491 (LPSTR)lpGroupName))
492 {
493 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
494 return FALSE;
495 }
496
497 bResult = DeleteGroupW(GroupName.Buffer, bCommonGroup);
498
499 RtlFreeUnicodeString(&GroupName);
500
501 return bResult;
502 }
503
504
505 BOOL WINAPI
506 DeleteGroupW (LPCWSTR lpGroupName,
507 BOOL bCommonGroup)
508 {
509 WCHAR szGroupPath[MAX_PATH];
510
511 DPRINT ("DeleteGroupW() called\n");
512
513 if (lpGroupName == NULL || *lpGroupName == 0)
514 return TRUE;
515
516 if (!GetProgramsPath (bCommonGroup, szGroupPath))
517 {
518 DPRINT1 ("GetProgramsPath() failed\n");
519 return FALSE;
520 }
521 DPRINT ("Programs path: '%S'\n", szGroupPath);
522
523 wcscat (szGroupPath, L"\\");
524 wcscat (szGroupPath, lpGroupName);
525 DPRINT ("Group path: '%S'\n", szGroupPath);
526
527 /* Remove directory path */
528 if (!RemoveDirectoryPath (szGroupPath))
529 return FALSE;
530
531 /* FIXME: Notify the shell */
532
533 DPRINT ("DeleteGroupW() done\n");
534
535 return TRUE;
536 }
537
538
539 BOOL WINAPI
540 AddItemA (LPCSTR lpGroupName, /* Optional */
541 BOOL bCommonGroup,
542 LPCSTR lpItemName,
543 LPCSTR lpArguments,
544 LPCSTR lpIconLocation,
545 INT iIcon,
546 LPCSTR lpWorkingDirectory, /* Optional */
547 WORD wHotKey,
548 INT iShowCmd)
549 {
550 UNICODE_STRING GroupName;
551 UNICODE_STRING ItemName;
552 UNICODE_STRING Arguments;
553 UNICODE_STRING IconLocation;
554 UNICODE_STRING WorkingDirectory;
555 BOOL bResult;
556
557 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName,
558 (LPSTR)lpItemName))
559 {
560 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
561 return FALSE;
562 }
563
564 if (!RtlCreateUnicodeStringFromAsciiz(&Arguments,
565 (LPSTR)lpArguments))
566 {
567 RtlFreeUnicodeString(&ItemName);
568 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
569 return FALSE;
570 }
571
572 if (!RtlCreateUnicodeStringFromAsciiz(&IconLocation,
573 (LPSTR)lpIconLocation))
574 {
575 RtlFreeUnicodeString(&Arguments);
576 RtlFreeUnicodeString(&ItemName);
577 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
578 return FALSE;
579 }
580
581 if (lpGroupName != NULL)
582 {
583 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName,
584 (LPSTR)lpGroupName))
585 {
586 RtlFreeUnicodeString(&IconLocation);
587 RtlFreeUnicodeString(&Arguments);
588 RtlFreeUnicodeString(&ItemName);
589 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
590 return FALSE;
591 }
592 }
593
594 if (lpWorkingDirectory != NULL)
595 {
596 if (!RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory,
597 (LPSTR)lpWorkingDirectory))
598 {
599 if (lpGroupName != NULL)
600 {
601 RtlFreeUnicodeString(&GroupName);
602 }
603 RtlFreeUnicodeString(&IconLocation);
604 RtlFreeUnicodeString(&Arguments);
605 RtlFreeUnicodeString(&ItemName);
606 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
607 return FALSE;
608 }
609 }
610
611 bResult = AddItemW((lpGroupName != NULL) ? GroupName.Buffer : NULL,
612 bCommonGroup,
613 ItemName.Buffer,
614 Arguments.Buffer,
615 IconLocation.Buffer,
616 iIcon,
617 (lpWorkingDirectory != NULL) ? WorkingDirectory.Buffer : NULL,
618 wHotKey,
619 iShowCmd);
620
621 if (lpGroupName != NULL)
622 {
623 RtlFreeUnicodeString(&GroupName);
624 }
625
626 if (lpWorkingDirectory != NULL)
627 {
628 RtlFreeUnicodeString(&WorkingDirectory);
629 }
630
631 RtlFreeUnicodeString(&IconLocation);
632 RtlFreeUnicodeString(&Arguments);
633 RtlFreeUnicodeString(&ItemName);
634
635 return bResult;
636 }
637
638
639 BOOL WINAPI
640 AddItemW (LPCWSTR lpGroupName, /* Optional */
641 BOOL bCommonGroup,
642 LPCWSTR lpItemName,
643 LPCWSTR lpArguments,
644 LPCWSTR lpIconLocation,
645 INT iIcon,
646 LPCWSTR lpWorkingDirectory, /* Optional */
647 WORD wHotKey,
648 INT iShowCmd)
649 {
650 DYN_FUNCS Ole32;
651 WCHAR szLinkPath[MAX_PATH];
652 WCHAR szArguments[MAX_PATH];
653 WCHAR szCommand[MAX_PATH];
654 WIN32_FIND_DATAW FindData;
655 HANDLE hFind;
656 LPWSTR Ptr;
657 DWORD dwLength;
658 IShellLinkW* psl;
659 IPersistFile* ppf;
660 HRESULT hr;
661 BOOL bResult;
662
663 DPRINT ("AddItemW() called\n");
664
665 bResult = FALSE;
666
667 if (!GetProgramsPath (bCommonGroup, szLinkPath))
668 {
669 DPRINT1 ("GetProgramsPath() failed\n");
670 return FALSE;
671 }
672
673 DPRINT ("Programs path: '%S'\n", szLinkPath);
674
675 if (lpGroupName != NULL && *lpGroupName != 0)
676 {
677 wcscat (szLinkPath, L"\\");
678 wcscat (szLinkPath, lpGroupName);
679
680 /* Make sure the path exists */
681 hFind = FindFirstFileW (szLinkPath,
682 &FindData);
683 if (hFind == INVALID_HANDLE_VALUE)
684 {
685 DPRINT ("'%S' does not exist\n", szLinkPath);
686 if (!CreateGroupW (lpGroupName,
687 bCommonGroup))
688 return FALSE;
689 }
690 else
691 {
692 DPRINT ("'%S' exists\n", szLinkPath);
693 FindClose (hFind);
694 }
695 }
696
697 wcscat (szLinkPath, L"\\");
698 wcscat (szLinkPath, lpItemName);
699 wcscat (szLinkPath, L".lnk");
700 DPRINT ("Link path: '%S'\n", szLinkPath);
701
702 /* Split 'lpArguments' string into command and arguments */
703 Ptr = wcschr (lpArguments, L' ');
704 DPRINT ("Ptr %p lpArguments %p\n", Ptr, lpArguments);
705 if (Ptr != NULL)
706 {
707 dwLength = (DWORD)(Ptr - lpArguments);
708 DPRINT ("dwLength %lu\n", dwLength);
709 memcpy (szCommand, lpArguments, dwLength * sizeof(WCHAR));
710 szCommand[dwLength] = 0;
711 Ptr++;
712 wcscpy (szArguments, Ptr);
713 }
714 else
715 {
716 wcscpy (szCommand, lpArguments);
717 szArguments[0] = 0;
718 }
719 DPRINT ("szCommand: '%S'\n", szCommand);
720 DPRINT ("szArguments: '%S'\n", szArguments);
721
722 /* Dynamically load ole32.dll */
723 if (!LoadDynamicImports(&DynOle32, &Ole32))
724 {
725 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
726 return FALSE;
727 }
728
729 Ole32.fn.CoInitialize(NULL);
730
731 hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink,
732 NULL,
733 CLSCTX_INPROC_SERVER,
734 &IID_IShellLinkW,
735 (LPVOID*)&psl);
736 if (!SUCCEEDED(hr))
737 {
738 Ole32.fn.CoUninitialize();
739 UnloadDynamicImports(&Ole32);
740 return FALSE;
741 }
742
743 hr = psl->lpVtbl->QueryInterface(psl,
744 &IID_IPersistFile,
745 (LPVOID*)&ppf);
746 if (SUCCEEDED(hr))
747 {
748 psl->lpVtbl->SetDescription(psl,
749 lpItemName);
750
751 psl->lpVtbl->SetPath(psl,
752 szCommand);
753
754 psl->lpVtbl->SetArguments(psl,
755 szArguments);
756
757 psl->lpVtbl->SetIconLocation(psl,
758 lpIconLocation,
759 iIcon);
760
761 if (lpWorkingDirectory != NULL)
762 {
763 psl->lpVtbl->SetWorkingDirectory(psl,
764 lpWorkingDirectory);
765 }
766 else
767 {
768 psl->lpVtbl->SetWorkingDirectory(psl,
769 L"%HOMEDRIVE%%HOMEPATH%");
770 }
771
772 psl->lpVtbl->SetHotkey(psl,
773 wHotKey);
774
775 psl->lpVtbl->SetShowCmd(psl,
776 iShowCmd);
777
778 hr = ppf->lpVtbl->Save(ppf,
779 szLinkPath,
780 TRUE);
781 if (SUCCEEDED(hr))
782 bResult = TRUE;
783
784 ppf->lpVtbl->Release(ppf);
785 }
786
787 psl->lpVtbl->Release(psl);
788
789 Ole32.fn.CoUninitialize();
790 UnloadDynamicImports(&Ole32);
791
792 DPRINT ("AddItemW() done\n");
793
794 return bResult;
795 }
796
797
798 BOOL WINAPI
799 DeleteItemA (LPCSTR lpGroupName, /* Optional */
800 BOOL bCommonGroup,
801 LPCSTR lpItemName,
802 BOOL bDeleteGroup)
803 {
804 UNICODE_STRING GroupName;
805 UNICODE_STRING ItemName;
806 BOOL bResult;
807
808 if (lpGroupName != NULL)
809 {
810 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName,
811 (LPSTR)lpGroupName))
812 {
813 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
814 return FALSE;
815 }
816 }
817
818 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName,
819 (LPSTR)lpItemName))
820 {
821 if (lpGroupName != NULL)
822 {
823 RtlFreeUnicodeString(&GroupName);
824 }
825
826 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
827 return FALSE;
828 }
829
830 bResult = DeleteItemW((lpGroupName != NULL) ? GroupName.Buffer : NULL,
831 bCommonGroup,
832 ItemName.Buffer,
833 bDeleteGroup);
834
835 RtlFreeUnicodeString(&ItemName);
836 if (lpGroupName != NULL)
837 {
838 RtlFreeUnicodeString(&GroupName);
839 }
840
841 return bResult;
842 }
843
844
845 BOOL WINAPI
846 DeleteItemW (LPCWSTR lpGroupName, /* Optional */
847 BOOL bCommonGroup,
848 LPCWSTR lpItemName,
849 BOOL bDeleteGroup)
850 {
851 WCHAR szItemPath[MAX_PATH];
852 LPWSTR Ptr;
853
854 DPRINT ("DeleteItemW() called\n");
855
856 if (!GetProgramsPath (bCommonGroup, szItemPath))
857 {
858 DPRINT1 ("GetProgramsPath() failed\n");
859 return FALSE;
860 }
861 DPRINT ("Programs path: '%S'\n", szItemPath);
862
863 if (lpGroupName != NULL && *lpGroupName != 0)
864 {
865 wcscat (szItemPath, L"\\");
866 wcscat (szItemPath, lpGroupName);
867 }
868
869 wcscat (szItemPath, L"\\");
870 wcscat (szItemPath, lpItemName);
871 wcscat (szItemPath, L".lnk");
872 DPRINT ("Item path: '%S'\n", szItemPath);
873
874 if (!DeleteFileW (szItemPath))
875 return FALSE;
876
877 /* FIXME: Notify the shell */
878
879 if (bDeleteGroup)
880 {
881 Ptr = wcsrchr (szItemPath, L'\\');
882 if (Ptr == NULL)
883 return TRUE;
884
885 *Ptr = 0;
886 DPRINT ("Item path: '%S'\n", szItemPath);
887 if (RemoveDirectoryW (szItemPath))
888 {
889 /* FIXME: Notify the shell */
890 }
891 }
892
893 DPRINT ("DeleteItemW() done\n");
894
895 return TRUE;
896 }
897
898 /* EOF */