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