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