3 * Copyright (C) 2004 ReactOS Team
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.
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.
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.
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
34 /* FUNCTIONS ***************************************************************/
37 GetDesktopPath (BOOL bCommonPath
,
40 WCHAR szPath
[MAX_PATH
];
46 DPRINT ("GetDesktopPath() called\n");
48 Error
= RegOpenKeyExW (HKEY_CURRENT_USER
,
49 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
53 if (Error
!= ERROR_SUCCESS
)
55 DPRINT1 ("RegOpenKeyExW() failed\n");
56 SetLastError((DWORD
)Error
);
60 dwLength
= MAX_PATH
* sizeof(WCHAR
);
61 Error
= RegQueryValueExW (hKey
,
62 bCommonPath
? L
"Common Desktop" : L
"Desktop",
67 if (Error
!= ERROR_SUCCESS
)
69 DPRINT1 ("RegQueryValueExW() failed\n");
71 SetLastError((DWORD
)Error
);
77 if (dwType
== REG_EXPAND_SZ
)
79 ExpandEnvironmentStringsW (szPath
,
85 wcscpy (lpDesktopPath
, szPath
);
88 DPRINT ("GetDesktopPath() done\n");
95 GetProgramsPath (BOOL bCommonPath
,
96 LPWSTR lpProgramsPath
)
98 WCHAR szPath
[MAX_PATH
];
104 DPRINT ("GetProgramsPath() called\n");
106 Error
= RegOpenKeyExW (HKEY_CURRENT_USER
,
107 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
111 if (Error
!= ERROR_SUCCESS
)
113 DPRINT1 ("RegOpenKeyExW() failed\n");
114 SetLastError((DWORD
)Error
);
118 dwLength
= MAX_PATH
* sizeof(WCHAR
);
119 Error
= RegQueryValueExW (hKey
,
120 bCommonPath
? L
"Common Programs" : L
"Programs",
125 if (Error
!= ERROR_SUCCESS
)
127 DPRINT1 ("RegQueryValueExW() failed\n");
129 SetLastError((DWORD
)Error
);
135 if (dwType
== REG_EXPAND_SZ
)
137 ExpandEnvironmentStringsW (szPath
,
143 wcscpy (lpProgramsPath
,
147 DPRINT ("GetProgramsPath() done\n");
154 AddDesktopItemA (BOOL bCommonItem
,
157 LPCSTR lpIconLocation
,
159 LPCSTR lpWorkingDirectory
, /* Optional */
163 UNICODE_STRING ItemName
;
164 UNICODE_STRING Arguments
;
165 UNICODE_STRING IconLocation
;
166 UNICODE_STRING WorkingDirectory
;
170 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
172 if (!NT_SUCCESS(Status
))
174 SetLastError (RtlNtStatusToDosError (Status
));
178 Status
= RtlCreateUnicodeStringFromAsciiz(&Arguments
,
180 if (!NT_SUCCESS(Status
))
182 RtlFreeUnicodeString(&ItemName
);
183 SetLastError (RtlNtStatusToDosError (Status
));
187 Status
= RtlCreateUnicodeStringFromAsciiz(&IconLocation
,
188 (LPSTR
)lpIconLocation
);
189 if (!NT_SUCCESS(Status
))
191 RtlFreeUnicodeString(&Arguments
);
192 RtlFreeUnicodeString(&ItemName
);
193 SetLastError (RtlNtStatusToDosError (Status
));
197 if (lpWorkingDirectory
!= NULL
)
199 Status
= RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory
,
200 (LPSTR
)lpWorkingDirectory
);
201 if (!NT_SUCCESS(Status
))
203 RtlFreeUnicodeString(&IconLocation
);
204 RtlFreeUnicodeString(&Arguments
);
205 RtlFreeUnicodeString(&ItemName
);
206 SetLastError (RtlNtStatusToDosError (Status
));
211 bResult
= AddDesktopItemW(bCommonItem
,
216 (lpWorkingDirectory
!= NULL
) ? WorkingDirectory
.Buffer
: NULL
,
220 if (lpWorkingDirectory
!= NULL
)
222 RtlFreeUnicodeString(&WorkingDirectory
);
225 RtlFreeUnicodeString(&IconLocation
);
226 RtlFreeUnicodeString(&Arguments
);
227 RtlFreeUnicodeString(&ItemName
);
234 AddDesktopItemW (BOOL bCommonDesktop
,
237 LPCWSTR lpIconLocation
,
239 LPCWSTR lpWorkingDirectory
, /* Optional */
244 WCHAR szLinkPath
[MAX_PATH
];
245 WCHAR szArguments
[MAX_PATH
];
246 WCHAR szCommand
[MAX_PATH
];
247 WIN32_FIND_DATAW FindData
;
256 DPRINT ("AddDesktopItemW() called\n");
260 if (!GetDesktopPath (bCommonDesktop
, szLinkPath
))
262 DPRINT1 ("GetDesktopPath() failed\n");
265 DPRINT ("Desktop path: '%S'\n", szLinkPath
);
267 /* Make sure the path exists */
268 hFind
= FindFirstFileW (szLinkPath
,
270 if (hFind
== INVALID_HANDLE_VALUE
)
272 DPRINT ("'%S' does not exist\n", szLinkPath
);
274 /* Create directory path */
275 if (!CreateDirectoryPath (szLinkPath
, NULL
))
280 DPRINT ("'%S' exists\n", szLinkPath
);
284 /* Append backslash, item name and ".lnk" extension */
285 wcscat (szLinkPath
, L
"\\");
286 wcscat (szLinkPath
, lpItemName
);
287 wcscat (szLinkPath
, L
".lnk");
288 DPRINT ("Link path: '%S'\n", szLinkPath
);
290 /* Split 'lpArguments' string into command and arguments */
291 Ptr
= wcschr (lpArguments
, L
' ');
292 DPRINT ("Ptr %p lpArguments %p\n", Ptr
, lpArguments
);
295 dwLength
= (DWORD
)(Ptr
- lpArguments
);
296 DPRINT ("dwLength %lu\n", dwLength
);
297 memcpy (szCommand
, lpArguments
, dwLength
* sizeof(WCHAR
));
298 szCommand
[dwLength
] = 0;
300 wcscpy (szArguments
, Ptr
);
304 wcscpy (szCommand
, lpArguments
);
307 DPRINT ("szCommand: '%S'\n", szCommand
);
308 DPRINT ("szArguments: '%S'\n", szArguments
);
310 /* Dynamically load ole32.dll */
311 if (!LoadDynamicImports(&DynOle32
, &Ole32
))
313 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
317 Ole32
.fn
.CoInitialize(NULL
);
319 hr
= Ole32
.fn
.CoCreateInstance(&CLSID_ShellLink
,
321 CLSCTX_INPROC_SERVER
,
326 Ole32
.fn
.CoUninitialize();
327 UnloadDynamicImports(&Ole32
);
331 hr
= psl
->lpVtbl
->QueryInterface(psl
,
336 psl
->lpVtbl
->SetDescription(psl
,
339 psl
->lpVtbl
->SetPath(psl
,
342 psl
->lpVtbl
->SetArguments(psl
,
345 psl
->lpVtbl
->SetIconLocation(psl
,
349 if (lpWorkingDirectory
!= NULL
)
351 psl
->lpVtbl
->SetWorkingDirectory(psl
,
356 psl
->lpVtbl
->SetWorkingDirectory(psl
,
357 L
"%HOMEDRIVE%%HOMEPATH%");
360 psl
->lpVtbl
->SetHotkey(psl
,
363 psl
->lpVtbl
->SetShowCmd(psl
,
366 hr
= ppf
->lpVtbl
->Save(ppf
,
372 ppf
->lpVtbl
->Release(ppf
);
375 psl
->lpVtbl
->Release(psl
);
377 Ole32
.fn
.CoUninitialize();
379 UnloadDynamicImports(&Ole32
);
381 DPRINT ("AddDesktopItemW() done\n");
388 DeleteDesktopItemA (BOOL bCommonItem
,
391 UNICODE_STRING ItemName
;
395 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
397 if (!NT_SUCCESS(Status
))
399 SetLastError (RtlNtStatusToDosError (Status
));
403 bResult
= DeleteDesktopItemW(bCommonItem
,
406 RtlFreeUnicodeString(&ItemName
);
413 DeleteDesktopItemW (BOOL bCommonItem
,
416 WCHAR szLinkPath
[MAX_PATH
];
418 DPRINT ("DeleteDesktopItemW() called\n");
420 if (!GetDesktopPath (bCommonItem
, szLinkPath
))
422 DPRINT1 ("GetDesktopPath() failed\n");
426 wcscat (szLinkPath
, L
"\\");
427 wcscat (szLinkPath
, lpItemName
);
428 wcscat (szLinkPath
, L
".lnk");
429 DPRINT ("Link path: '%S'\n", szLinkPath
);
431 return DeleteFileW (szLinkPath
);
436 CreateGroupA (LPCSTR lpGroupName
,
439 UNICODE_STRING GroupName
;
443 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
445 if (!NT_SUCCESS(Status
))
447 SetLastError (RtlNtStatusToDosError (Status
));
451 bResult
= CreateGroupW(GroupName
.Buffer
, bCommonGroup
);
453 RtlFreeUnicodeString(&GroupName
);
460 CreateGroupW (LPCWSTR lpGroupName
,
463 WCHAR szGroupPath
[MAX_PATH
];
465 DPRINT1 ("CreateGroupW() called\n");
467 if (lpGroupName
== NULL
|| *lpGroupName
== 0)
470 if (!GetProgramsPath (bCommonGroup
, szGroupPath
))
472 DPRINT1 ("GetProgramsPath() failed\n");
475 DPRINT1 ("Programs path: '%S'\n", szGroupPath
);
477 wcscat (szGroupPath
, L
"\\");
478 wcscat (szGroupPath
, lpGroupName
);
479 DPRINT1 ("Group path: '%S'\n", szGroupPath
);
481 /* Create directory path */
482 if (!CreateDirectoryPath (szGroupPath
, NULL
))
485 /* FIXME: Notify the shell */
487 DPRINT1 ("CreateGroupW() done\n");
494 DeleteGroupA (LPCSTR lpGroupName
,
497 UNICODE_STRING GroupName
;
501 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
503 if (!NT_SUCCESS(Status
))
505 SetLastError (RtlNtStatusToDosError (Status
));
509 bResult
= DeleteGroupW(GroupName
.Buffer
, bCommonGroup
);
511 RtlFreeUnicodeString(&GroupName
);
518 DeleteGroupW (LPCWSTR lpGroupName
,
521 WCHAR szGroupPath
[MAX_PATH
];
523 DPRINT ("DeleteGroupW() called\n");
525 if (lpGroupName
== NULL
|| *lpGroupName
== 0)
528 if (!GetProgramsPath (bCommonGroup
, szGroupPath
))
530 DPRINT1 ("GetProgramsPath() failed\n");
533 DPRINT ("Programs path: '%S'\n", szGroupPath
);
535 wcscat (szGroupPath
, L
"\\");
536 wcscat (szGroupPath
, lpGroupName
);
537 DPRINT ("Group path: '%S'\n", szGroupPath
);
539 /* Remove directory path */
540 if (!RemoveDirectoryPath (szGroupPath
))
543 /* FIXME: Notify the shell */
545 DPRINT ("DeleteGroupW() done\n");
552 AddItemA (LPCSTR lpGroupName
, /* Optional */
556 LPCSTR lpIconLocation
,
558 LPCSTR lpWorkingDirectory
, /* Optional */
562 UNICODE_STRING GroupName
;
563 UNICODE_STRING ItemName
;
564 UNICODE_STRING Arguments
;
565 UNICODE_STRING IconLocation
;
566 UNICODE_STRING WorkingDirectory
;
570 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
572 if (!NT_SUCCESS(Status
))
574 SetLastError (RtlNtStatusToDosError (Status
));
578 Status
= RtlCreateUnicodeStringFromAsciiz(&Arguments
,
580 if (!NT_SUCCESS(Status
))
582 RtlFreeUnicodeString(&ItemName
);
583 SetLastError (RtlNtStatusToDosError (Status
));
587 Status
= RtlCreateUnicodeStringFromAsciiz(&IconLocation
,
588 (LPSTR
)lpIconLocation
);
589 if (!NT_SUCCESS(Status
))
591 RtlFreeUnicodeString(&Arguments
);
592 RtlFreeUnicodeString(&ItemName
);
593 SetLastError (RtlNtStatusToDosError (Status
));
597 if (lpGroupName
!= NULL
)
599 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
601 if (!NT_SUCCESS(Status
))
603 RtlFreeUnicodeString(&IconLocation
);
604 RtlFreeUnicodeString(&Arguments
);
605 RtlFreeUnicodeString(&ItemName
);
606 SetLastError (RtlNtStatusToDosError (Status
));
611 if (lpWorkingDirectory
!= NULL
)
613 Status
= RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory
,
614 (LPSTR
)lpWorkingDirectory
);
615 if (!NT_SUCCESS(Status
))
617 if (lpGroupName
!= NULL
)
619 RtlFreeUnicodeString(&GroupName
);
621 RtlFreeUnicodeString(&IconLocation
);
622 RtlFreeUnicodeString(&Arguments
);
623 RtlFreeUnicodeString(&ItemName
);
624 SetLastError (RtlNtStatusToDosError (Status
));
629 bResult
= AddItemW((lpGroupName
!= NULL
) ? GroupName
.Buffer
: NULL
,
635 (lpWorkingDirectory
!= NULL
) ? WorkingDirectory
.Buffer
: NULL
,
639 if (lpGroupName
!= NULL
)
641 RtlFreeUnicodeString(&GroupName
);
644 if (lpWorkingDirectory
!= NULL
)
646 RtlFreeUnicodeString(&WorkingDirectory
);
649 RtlFreeUnicodeString(&IconLocation
);
650 RtlFreeUnicodeString(&Arguments
);
651 RtlFreeUnicodeString(&ItemName
);
658 AddItemW (LPCWSTR lpGroupName
, /* Optional */
662 LPCWSTR lpIconLocation
,
664 LPCWSTR lpWorkingDirectory
, /* Optional */
669 WCHAR szLinkPath
[MAX_PATH
];
670 WCHAR szArguments
[MAX_PATH
];
671 WCHAR szCommand
[MAX_PATH
];
672 WIN32_FIND_DATAW FindData
;
681 DPRINT ("AddItemW() called\n");
685 if (!GetProgramsPath (bCommonGroup
, szLinkPath
))
687 DPRINT1 ("GetProgramsPath() failed\n");
691 DPRINT ("Programs path: '%S'\n", szLinkPath
);
693 if (lpGroupName
!= NULL
&& *lpGroupName
!= 0)
695 wcscat (szLinkPath
, L
"\\");
696 wcscat (szLinkPath
, lpGroupName
);
698 /* Make sure the path exists */
699 hFind
= FindFirstFileW (szLinkPath
,
701 if (hFind
== INVALID_HANDLE_VALUE
)
703 DPRINT ("'%S' does not exist\n", szLinkPath
);
704 if (!CreateGroupW (lpGroupName
,
710 DPRINT ("'%S' exists\n", szLinkPath
);
715 wcscat (szLinkPath
, L
"\\");
716 wcscat (szLinkPath
, lpItemName
);
717 wcscat (szLinkPath
, L
".lnk");
718 DPRINT ("Link path: '%S'\n", szLinkPath
);
720 /* Split 'lpArguments' string into command and arguments */
721 Ptr
= wcschr (lpArguments
, L
' ');
722 DPRINT ("Ptr %p lpArguments %p\n", Ptr
, lpArguments
);
725 dwLength
= (DWORD
)(Ptr
- lpArguments
);
726 DPRINT ("dwLength %lu\n", dwLength
);
727 memcpy (szCommand
, lpArguments
, dwLength
* sizeof(WCHAR
));
728 szCommand
[dwLength
] = 0;
730 wcscpy (szArguments
, Ptr
);
734 wcscpy (szCommand
, lpArguments
);
737 DPRINT ("szCommand: '%S'\n", szCommand
);
738 DPRINT ("szArguments: '%S'\n", szArguments
);
740 /* Dynamically load ole32.dll */
741 if (!LoadDynamicImports(&DynOle32
, &Ole32
))
743 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
747 Ole32
.fn
.CoInitialize(NULL
);
749 hr
= Ole32
.fn
.CoCreateInstance(&CLSID_ShellLink
,
751 CLSCTX_INPROC_SERVER
,
756 Ole32
.fn
.CoUninitialize();
757 UnloadDynamicImports(&Ole32
);
761 hr
= psl
->lpVtbl
->QueryInterface(psl
,
766 psl
->lpVtbl
->SetDescription(psl
,
769 psl
->lpVtbl
->SetPath(psl
,
772 psl
->lpVtbl
->SetArguments(psl
,
775 psl
->lpVtbl
->SetIconLocation(psl
,
779 if (lpWorkingDirectory
!= NULL
)
781 psl
->lpVtbl
->SetWorkingDirectory(psl
,
786 psl
->lpVtbl
->SetWorkingDirectory(psl
,
787 L
"%HOMEDRIVE%%HOMEPATH%");
790 psl
->lpVtbl
->SetHotkey(psl
,
793 psl
->lpVtbl
->SetShowCmd(psl
,
796 hr
= ppf
->lpVtbl
->Save(ppf
,
802 ppf
->lpVtbl
->Release(ppf
);
805 psl
->lpVtbl
->Release(psl
);
807 Ole32
.fn
.CoUninitialize();
808 UnloadDynamicImports(&Ole32
);
810 DPRINT ("AddItemW() done\n");
817 DeleteItemA (LPCSTR lpGroupName
, /* Optional */
822 UNICODE_STRING GroupName
;
823 UNICODE_STRING ItemName
;
827 if (lpGroupName
!= NULL
)
829 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
831 if (!NT_SUCCESS(Status
))
833 SetLastError (RtlNtStatusToDosError (Status
));
838 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
840 if (!NT_SUCCESS(Status
))
842 if (lpGroupName
!= NULL
)
844 RtlFreeUnicodeString(&GroupName
);
847 SetLastError (RtlNtStatusToDosError (Status
));
851 bResult
= DeleteItemW((lpGroupName
!= NULL
) ? GroupName
.Buffer
: NULL
,
856 RtlFreeUnicodeString(&ItemName
);
857 if (lpGroupName
!= NULL
)
859 RtlFreeUnicodeString(&GroupName
);
867 DeleteItemW (LPCWSTR lpGroupName
, /* Optional */
872 WCHAR szItemPath
[MAX_PATH
];
875 DPRINT ("DeleteItemW() called\n");
877 if (!GetProgramsPath (bCommonGroup
, szItemPath
))
879 DPRINT1 ("GetProgramsPath() failed\n");
882 DPRINT ("Programs path: '%S'\n", szItemPath
);
884 if (lpGroupName
!= NULL
&& *lpGroupName
!= 0)
886 wcscat (szItemPath
, L
"\\");
887 wcscat (szItemPath
, lpGroupName
);
890 wcscat (szItemPath
, L
"\\");
891 wcscat (szItemPath
, lpItemName
);
892 wcscat (szItemPath
, L
".lnk");
893 DPRINT ("Item path: '%S'\n", szItemPath
);
895 if (!DeleteFileW (szItemPath
))
898 /* FIXME: Notify the shell */
902 Ptr
= wcsrchr (szItemPath
, L
'\\');
907 DPRINT ("Item path: '%S'\n", szItemPath
);
908 if (RemoveDirectoryW (szItemPath
))
910 /* FIXME: Notify the shell */
914 DPRINT ("DeleteItemW() done\n");