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