xref: /reactos/dll/win32/userenv/desktop.c (revision c2c66aff)
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