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
];
45 DPRINT ("GetDesktopPath() called\n");
47 if (RegOpenKeyExW (HKEY_CURRENT_USER
,
48 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
53 DPRINT1 ("RegOpenKeyExW() failed\n");
57 dwLength
= MAX_PATH
* sizeof(WCHAR
);
58 if (RegQueryValueExW (hKey
,
59 bCommonPath
? L
"Common Desktop" : L
"Desktop",
65 DPRINT1 ("RegQueryValueExW() failed\n");
72 if (dwType
== REG_EXPAND_SZ
)
74 ExpandEnvironmentStringsW (szPath
,
80 wcscpy (lpDesktopPath
, szPath
);
83 DPRINT ("GetDesktopPath() done\n");
90 GetProgramsPath (BOOL bCommonPath
,
91 LPWSTR lpProgramsPath
)
93 WCHAR szPath
[MAX_PATH
];
98 DPRINT ("GetProgramsPath() called\n");
100 if (RegOpenKeyExW (HKEY_CURRENT_USER
,
101 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
106 DPRINT1 ("RegOpenKeyExW() failed\n");
110 dwLength
= MAX_PATH
* sizeof(WCHAR
);
111 if (RegQueryValueExW (hKey
,
112 bCommonPath
? L
"Common Programs" : L
"Programs",
118 DPRINT1 ("RegQueryValueExW() failed\n");
125 if (dwType
== REG_EXPAND_SZ
)
127 ExpandEnvironmentStringsW (szPath
,
133 wcscpy (lpProgramsPath
,
137 DPRINT ("GetProgramsPath() done\n");
144 AddDesktopItemA (BOOL bCommonItem
,
147 LPCSTR lpIconLocation
,
149 LPCSTR lpWorkingDirectory
, /* Optional */
153 UNICODE_STRING ItemName
;
154 UNICODE_STRING Arguments
;
155 UNICODE_STRING IconLocation
;
156 UNICODE_STRING WorkingDirectory
;
160 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
162 if (!NT_SUCCESS(Status
))
164 SetLastError (RtlNtStatusToDosError (Status
));
168 Status
= RtlCreateUnicodeStringFromAsciiz(&Arguments
,
170 if (!NT_SUCCESS(Status
))
172 RtlFreeUnicodeString(&ItemName
);
173 SetLastError (RtlNtStatusToDosError (Status
));
177 Status
= RtlCreateUnicodeStringFromAsciiz(&IconLocation
,
178 (LPSTR
)lpIconLocation
);
179 if (!NT_SUCCESS(Status
))
181 RtlFreeUnicodeString(&Arguments
);
182 RtlFreeUnicodeString(&ItemName
);
183 SetLastError (RtlNtStatusToDosError (Status
));
187 if (lpWorkingDirectory
!= NULL
)
189 Status
= RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory
,
190 (LPSTR
)lpWorkingDirectory
);
191 if (!NT_SUCCESS(Status
))
193 RtlFreeUnicodeString(&IconLocation
);
194 RtlFreeUnicodeString(&Arguments
);
195 RtlFreeUnicodeString(&ItemName
);
196 SetLastError (RtlNtStatusToDosError (Status
));
201 bResult
= AddDesktopItemW(bCommonItem
,
206 (lpWorkingDirectory
!= NULL
) ? WorkingDirectory
.Buffer
: NULL
,
210 if (lpWorkingDirectory
!= NULL
)
212 RtlFreeUnicodeString(&WorkingDirectory
);
215 RtlFreeUnicodeString(&IconLocation
);
216 RtlFreeUnicodeString(&Arguments
);
217 RtlFreeUnicodeString(&ItemName
);
224 AddDesktopItemW (BOOL bCommonDesktop
,
227 LPCWSTR lpIconLocation
,
229 LPCWSTR lpWorkingDirectory
, /* Optional */
234 WCHAR szLinkPath
[MAX_PATH
];
235 WCHAR szArguments
[MAX_PATH
];
236 WCHAR szCommand
[MAX_PATH
];
237 WIN32_FIND_DATAW FindData
;
246 DPRINT ("AddDesktopItemW() called\n");
250 if (!GetDesktopPath (bCommonDesktop
, szLinkPath
))
252 DPRINT1 ("GetDesktopPath() failed\n");
255 DPRINT ("Desktop path: '%S'\n", szLinkPath
);
257 /* Make sure the path exists */
258 hFind
= FindFirstFileW (szLinkPath
,
260 if (hFind
== INVALID_HANDLE_VALUE
)
262 DPRINT ("'%S' does not exist\n", szLinkPath
);
264 /* Create directory path */
265 if (!CreateDirectoryPath (szLinkPath
, NULL
))
270 DPRINT ("'%S' exists\n", szLinkPath
);
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
);
280 /* Split 'lpArguments' string into command and arguments */
281 Ptr
= wcschr (lpArguments
, L
' ');
282 DPRINT ("Ptr %p lpArguments %p\n", Ptr
, lpArguments
);
285 dwLength
= (DWORD
)(Ptr
- lpArguments
);
286 DPRINT ("dwLength %lu\n", dwLength
);
287 memcpy (szCommand
, lpArguments
, dwLength
* sizeof(WCHAR
));
288 szCommand
[dwLength
] = 0;
290 wcscpy (szArguments
, Ptr
);
294 wcscpy (szCommand
, lpArguments
);
297 DPRINT ("szCommand: '%S'\n", szCommand
);
298 DPRINT ("szArguments: '%S'\n", szArguments
);
300 /* Dynamically load ole32.dll */
301 if (!LoadDynamicImports(&DynOle32
, &Ole32
))
303 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
307 Ole32
.fn
.CoInitialize(NULL
);
309 hr
= Ole32
.fn
.CoCreateInstance(&CLSID_ShellLink
,
311 CLSCTX_INPROC_SERVER
,
316 Ole32
.fn
.CoUninitialize();
317 UnloadDynamicImports(&Ole32
);
321 hr
= psl
->lpVtbl
->QueryInterface(psl
,
326 psl
->lpVtbl
->SetDescription(psl
,
329 psl
->lpVtbl
->SetPath(psl
,
332 psl
->lpVtbl
->SetArguments(psl
,
335 psl
->lpVtbl
->SetIconLocation(psl
,
339 if (lpWorkingDirectory
!= NULL
)
341 psl
->lpVtbl
->SetWorkingDirectory(psl
,
346 psl
->lpVtbl
->SetWorkingDirectory(psl
,
347 L
"%HOMEDRIVE%%HOMEPATH%");
350 psl
->lpVtbl
->SetHotkey(psl
,
353 psl
->lpVtbl
->SetShowCmd(psl
,
356 hr
= ppf
->lpVtbl
->Save(ppf
,
362 ppf
->lpVtbl
->Release(ppf
);
365 psl
->lpVtbl
->Release(psl
);
367 Ole32
.fn
.CoUninitialize();
369 UnloadDynamicImports(&Ole32
);
371 DPRINT ("AddDesktopItemW() done\n");
378 DeleteDesktopItemA (BOOL bCommonItem
,
381 UNICODE_STRING ItemName
;
385 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
387 if (!NT_SUCCESS(Status
))
389 SetLastError (RtlNtStatusToDosError (Status
));
393 bResult
= DeleteDesktopItemW(bCommonItem
,
396 RtlFreeUnicodeString(&ItemName
);
403 DeleteDesktopItemW (BOOL bCommonItem
,
406 WCHAR szLinkPath
[MAX_PATH
];
408 DPRINT ("DeleteDesktopItemW() called\n");
410 if (!GetDesktopPath (bCommonItem
, szLinkPath
))
412 DPRINT1 ("GetDesktopPath() failed\n");
416 wcscat (szLinkPath
, L
"\\");
417 wcscat (szLinkPath
, lpItemName
);
418 wcscat (szLinkPath
, L
".lnk");
419 DPRINT ("Link path: '%S'\n", szLinkPath
);
421 return DeleteFileW (szLinkPath
);
426 CreateGroupA (LPCSTR lpGroupName
,
429 UNICODE_STRING GroupName
;
433 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
435 if (!NT_SUCCESS(Status
))
437 SetLastError (RtlNtStatusToDosError (Status
));
441 bResult
= CreateGroupW(GroupName
.Buffer
, bCommonGroup
);
443 RtlFreeUnicodeString(&GroupName
);
450 CreateGroupW (LPCWSTR lpGroupName
,
453 WCHAR szGroupPath
[MAX_PATH
];
455 DPRINT1 ("CreateGroupW() called\n");
457 if (lpGroupName
== NULL
|| *lpGroupName
== 0)
460 if (!GetProgramsPath (bCommonGroup
, szGroupPath
))
462 DPRINT1 ("GetProgramsPath() failed\n");
465 DPRINT1 ("Programs path: '%S'\n", szGroupPath
);
467 wcscat (szGroupPath
, L
"\\");
468 wcscat (szGroupPath
, lpGroupName
);
469 DPRINT1 ("Group path: '%S'\n", szGroupPath
);
471 /* Create directory path */
472 if (!CreateDirectoryPath (szGroupPath
, NULL
))
475 /* FIXME: Notify the shell */
477 DPRINT1 ("CreateGroupW() done\n");
484 DeleteGroupA (LPCSTR lpGroupName
,
487 UNICODE_STRING GroupName
;
491 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
493 if (!NT_SUCCESS(Status
))
495 SetLastError (RtlNtStatusToDosError (Status
));
499 bResult
= DeleteGroupW(GroupName
.Buffer
, bCommonGroup
);
501 RtlFreeUnicodeString(&GroupName
);
508 DeleteGroupW (LPCWSTR lpGroupName
,
511 WCHAR szGroupPath
[MAX_PATH
];
513 DPRINT ("DeleteGroupW() called\n");
515 if (lpGroupName
== NULL
|| *lpGroupName
== 0)
518 if (!GetProgramsPath (bCommonGroup
, szGroupPath
))
520 DPRINT1 ("GetProgramsPath() failed\n");
523 DPRINT ("Programs path: '%S'\n", szGroupPath
);
525 wcscat (szGroupPath
, L
"\\");
526 wcscat (szGroupPath
, lpGroupName
);
527 DPRINT ("Group path: '%S'\n", szGroupPath
);
529 /* Remove directory path */
530 if (!RemoveDirectoryPath (szGroupPath
))
533 /* FIXME: Notify the shell */
535 DPRINT ("DeleteGroupW() done\n");
542 AddItemA (LPCSTR lpGroupName
, /* Optional */
546 LPCSTR lpIconLocation
,
548 LPCSTR lpWorkingDirectory
, /* Optional */
552 UNICODE_STRING GroupName
;
553 UNICODE_STRING ItemName
;
554 UNICODE_STRING Arguments
;
555 UNICODE_STRING IconLocation
;
556 UNICODE_STRING WorkingDirectory
;
560 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
562 if (!NT_SUCCESS(Status
))
564 SetLastError (RtlNtStatusToDosError (Status
));
568 Status
= RtlCreateUnicodeStringFromAsciiz(&Arguments
,
570 if (!NT_SUCCESS(Status
))
572 RtlFreeUnicodeString(&ItemName
);
573 SetLastError (RtlNtStatusToDosError (Status
));
577 Status
= RtlCreateUnicodeStringFromAsciiz(&IconLocation
,
578 (LPSTR
)lpIconLocation
);
579 if (!NT_SUCCESS(Status
))
581 RtlFreeUnicodeString(&Arguments
);
582 RtlFreeUnicodeString(&ItemName
);
583 SetLastError (RtlNtStatusToDosError (Status
));
587 if (lpGroupName
!= NULL
)
589 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
591 if (!NT_SUCCESS(Status
))
593 RtlFreeUnicodeString(&IconLocation
);
594 RtlFreeUnicodeString(&Arguments
);
595 RtlFreeUnicodeString(&ItemName
);
596 SetLastError (RtlNtStatusToDosError (Status
));
601 if (lpWorkingDirectory
!= NULL
)
603 Status
= RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory
,
604 (LPSTR
)lpWorkingDirectory
);
605 if (!NT_SUCCESS(Status
))
607 if (lpGroupName
!= NULL
)
609 RtlFreeUnicodeString(&GroupName
);
611 RtlFreeUnicodeString(&IconLocation
);
612 RtlFreeUnicodeString(&Arguments
);
613 RtlFreeUnicodeString(&ItemName
);
614 SetLastError (RtlNtStatusToDosError (Status
));
619 bResult
= AddItemW((lpGroupName
!= NULL
) ? GroupName
.Buffer
: NULL
,
625 (lpWorkingDirectory
!= NULL
) ? WorkingDirectory
.Buffer
: NULL
,
629 if (lpGroupName
!= NULL
)
631 RtlFreeUnicodeString(&GroupName
);
634 if (lpWorkingDirectory
!= NULL
)
636 RtlFreeUnicodeString(&WorkingDirectory
);
639 RtlFreeUnicodeString(&IconLocation
);
640 RtlFreeUnicodeString(&Arguments
);
641 RtlFreeUnicodeString(&ItemName
);
648 AddItemW (LPCWSTR lpGroupName
, /* Optional */
652 LPCWSTR lpIconLocation
,
654 LPCWSTR lpWorkingDirectory
, /* Optional */
659 WCHAR szLinkPath
[MAX_PATH
];
660 WCHAR szArguments
[MAX_PATH
];
661 WCHAR szCommand
[MAX_PATH
];
662 WIN32_FIND_DATAW FindData
;
671 DPRINT ("AddItemW() called\n");
675 if (!GetProgramsPath (bCommonGroup
, szLinkPath
))
677 DPRINT1 ("GetProgramsPath() failed\n");
681 DPRINT ("Programs path: '%S'\n", szLinkPath
);
683 if (lpGroupName
!= NULL
&& *lpGroupName
!= 0)
685 wcscat (szLinkPath
, L
"\\");
686 wcscat (szLinkPath
, lpGroupName
);
688 /* Make sure the path exists */
689 hFind
= FindFirstFileW (szLinkPath
,
691 if (hFind
== INVALID_HANDLE_VALUE
)
693 DPRINT ("'%S' does not exist\n", szLinkPath
);
694 if (!CreateGroupW (lpGroupName
,
700 DPRINT ("'%S' exists\n", szLinkPath
);
705 wcscat (szLinkPath
, L
"\\");
706 wcscat (szLinkPath
, lpItemName
);
707 wcscat (szLinkPath
, L
".lnk");
708 DPRINT ("Link path: '%S'\n", szLinkPath
);
710 /* Split 'lpArguments' string into command and arguments */
711 Ptr
= wcschr (lpArguments
, L
' ');
712 DPRINT ("Ptr %p lpArguments %p\n", Ptr
, lpArguments
);
715 dwLength
= (DWORD
)(Ptr
- lpArguments
);
716 DPRINT ("dwLength %lu\n", dwLength
);
717 memcpy (szCommand
, lpArguments
, dwLength
* sizeof(WCHAR
));
718 szCommand
[dwLength
] = 0;
720 wcscpy (szArguments
, Ptr
);
724 wcscpy (szCommand
, lpArguments
);
727 DPRINT ("szCommand: '%S'\n", szCommand
);
728 DPRINT ("szArguments: '%S'\n", szArguments
);
730 /* Dynamically load ole32.dll */
731 if (!LoadDynamicImports(&DynOle32
, &Ole32
))
733 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
737 Ole32
.fn
.CoInitialize(NULL
);
739 hr
= Ole32
.fn
.CoCreateInstance(&CLSID_ShellLink
,
741 CLSCTX_INPROC_SERVER
,
746 Ole32
.fn
.CoUninitialize();
747 UnloadDynamicImports(&Ole32
);
751 hr
= psl
->lpVtbl
->QueryInterface(psl
,
756 psl
->lpVtbl
->SetDescription(psl
,
759 psl
->lpVtbl
->SetPath(psl
,
762 psl
->lpVtbl
->SetArguments(psl
,
765 psl
->lpVtbl
->SetIconLocation(psl
,
769 if (lpWorkingDirectory
!= NULL
)
771 psl
->lpVtbl
->SetWorkingDirectory(psl
,
776 psl
->lpVtbl
->SetWorkingDirectory(psl
,
777 L
"%HOMEDRIVE%%HOMEPATH%");
780 psl
->lpVtbl
->SetHotkey(psl
,
783 psl
->lpVtbl
->SetShowCmd(psl
,
786 hr
= ppf
->lpVtbl
->Save(ppf
,
792 ppf
->lpVtbl
->Release(ppf
);
795 psl
->lpVtbl
->Release(psl
);
797 Ole32
.fn
.CoUninitialize();
798 UnloadDynamicImports(&Ole32
);
800 DPRINT ("AddItemW() done\n");
807 DeleteItemA (LPCSTR lpGroupName
, /* Optional */
812 UNICODE_STRING GroupName
;
813 UNICODE_STRING ItemName
;
817 if (lpGroupName
!= NULL
)
819 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
821 if (!NT_SUCCESS(Status
))
823 SetLastError (RtlNtStatusToDosError (Status
));
828 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
830 if (!NT_SUCCESS(Status
))
832 if (lpGroupName
!= NULL
)
834 RtlFreeUnicodeString(&GroupName
);
837 SetLastError (RtlNtStatusToDosError (Status
));
841 bResult
= DeleteItemW((lpGroupName
!= NULL
) ? GroupName
.Buffer
: NULL
,
846 RtlFreeUnicodeString(&ItemName
);
847 if (lpGroupName
!= NULL
)
849 RtlFreeUnicodeString(&GroupName
);
857 DeleteItemW (LPCWSTR lpGroupName
, /* Optional */
862 WCHAR szItemPath
[MAX_PATH
];
865 DPRINT ("DeleteItemW() called\n");
867 if (!GetProgramsPath (bCommonGroup
, szItemPath
))
869 DPRINT1 ("GetProgramsPath() failed\n");
872 DPRINT ("Programs path: '%S'\n", szItemPath
);
874 if (lpGroupName
!= NULL
&& *lpGroupName
!= 0)
876 wcscat (szItemPath
, L
"\\");
877 wcscat (szItemPath
, lpGroupName
);
880 wcscat (szItemPath
, L
"\\");
881 wcscat (szItemPath
, lpItemName
);
882 wcscat (szItemPath
, L
".lnk");
883 DPRINT ("Item path: '%S'\n", szItemPath
);
885 if (!DeleteFileW (szItemPath
))
888 /* FIXME: Notify the shell */
892 Ptr
= wcsrchr (szItemPath
, L
'\\');
897 DPRINT ("Item path: '%S'\n", szItemPath
);
898 if (RemoveDirectoryW (szItemPath
))
900 /* FIXME: Notify the shell */
904 DPRINT ("DeleteItemW() done\n");