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
32 /* FUNCTIONS ***************************************************************/
35 GetDesktopPath (BOOL bCommonPath
,
38 WCHAR szPath
[MAX_PATH
];
43 DPRINT ("GetDesktopPath() called\n");
45 if (RegOpenKeyExW (HKEY_CURRENT_USER
,
46 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
51 DPRINT1 ("RegOpenKeyExW() failed\n");
55 dwLength
= MAX_PATH
* sizeof(WCHAR
);
56 if (RegQueryValueExW (hKey
,
57 bCommonPath
? L
"Common Desktop" : L
"Desktop",
63 DPRINT1 ("RegQueryValueExW() failed\n");
70 if (dwType
== REG_EXPAND_SZ
)
72 ExpandEnvironmentStringsW (szPath
,
78 wcscpy (lpDesktopPath
, szPath
);
81 DPRINT ("GetDesktopPath() done\n");
88 GetProgramsPath (BOOL bCommonPath
,
89 LPWSTR lpProgramsPath
)
91 WCHAR szPath
[MAX_PATH
];
96 DPRINT ("GetProgramsPath() called\n");
98 if (RegOpenKeyExW (HKEY_CURRENT_USER
,
99 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
104 DPRINT1 ("RegOpenKeyExW() failed\n");
108 dwLength
= MAX_PATH
* sizeof(WCHAR
);
109 if (RegQueryValueExW (hKey
,
110 bCommonPath
? L
"Common Programs" : L
"Programs",
116 DPRINT1 ("RegQueryValueExW() failed\n");
123 if (dwType
== REG_EXPAND_SZ
)
125 ExpandEnvironmentStringsW (szPath
,
131 wcscpy (lpProgramsPath
,
135 DPRINT ("GetProgramsPath() done\n");
142 AddDesktopItemA (BOOL bCommonItem
,
145 LPCSTR lpIconLocation
,
147 LPCSTR lpWorkingDirectory
, /* Optional */
151 UNICODE_STRING ItemName
;
152 UNICODE_STRING Arguments
;
153 UNICODE_STRING IconLocation
;
154 UNICODE_STRING WorkingDirectory
;
158 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
160 if (!NT_SUCCESS(Status
))
162 SetLastError (RtlNtStatusToDosError (Status
));
166 Status
= RtlCreateUnicodeStringFromAsciiz(&Arguments
,
168 if (!NT_SUCCESS(Status
))
170 RtlFreeUnicodeString(&ItemName
);
171 SetLastError (RtlNtStatusToDosError (Status
));
175 Status
= RtlCreateUnicodeStringFromAsciiz(&IconLocation
,
176 (LPSTR
)lpIconLocation
);
177 if (!NT_SUCCESS(Status
))
179 RtlFreeUnicodeString(&Arguments
);
180 RtlFreeUnicodeString(&ItemName
);
181 SetLastError (RtlNtStatusToDosError (Status
));
185 if (lpWorkingDirectory
!= NULL
)
187 Status
= RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory
,
188 (LPSTR
)lpWorkingDirectory
);
189 if (!NT_SUCCESS(Status
))
191 RtlFreeUnicodeString(&IconLocation
);
192 RtlFreeUnicodeString(&Arguments
);
193 RtlFreeUnicodeString(&ItemName
);
194 SetLastError (RtlNtStatusToDosError (Status
));
199 bResult
= AddDesktopItemW(bCommonItem
,
204 (lpWorkingDirectory
!= NULL
) ? WorkingDirectory
.Buffer
: NULL
,
208 if (lpWorkingDirectory
!= NULL
)
210 RtlFreeUnicodeString(&WorkingDirectory
);
213 RtlFreeUnicodeString(&IconLocation
);
214 RtlFreeUnicodeString(&Arguments
);
215 RtlFreeUnicodeString(&ItemName
);
222 AddDesktopItemW (BOOL bCommonDesktop
,
225 LPCWSTR lpIconLocation
,
227 LPCWSTR lpWorkingDirectory
, /* Optional */
232 WCHAR szLinkPath
[MAX_PATH
];
233 WCHAR szArguments
[MAX_PATH
];
234 WCHAR szCommand
[MAX_PATH
];
235 WIN32_FIND_DATAW FindData
;
244 DPRINT ("AddDesktopItemW() called\n");
248 if (!GetDesktopPath (bCommonDesktop
, szLinkPath
))
250 DPRINT1 ("GetDesktopPath() failed\n");
253 DPRINT ("Desktop path: '%S'\n", szLinkPath
);
255 /* Make sure the path exists */
256 hFind
= FindFirstFileW (szLinkPath
,
258 if (hFind
== INVALID_HANDLE_VALUE
)
260 DPRINT ("'%S' does not exist\n", szLinkPath
);
262 /* Create directory path */
263 if (!CreateDirectoryPath (szLinkPath
, NULL
))
268 DPRINT ("'%S' exists\n", szLinkPath
);
272 /* Append backslash, item name and ".lnk" extension */
273 wcscat (szLinkPath
, L
"\\");
274 wcscat (szLinkPath
, lpItemName
);
275 wcscat (szLinkPath
, L
".lnk");
276 DPRINT ("Link path: '%S'\n", szLinkPath
);
278 /* Split 'lpArguments' string into command and arguments */
279 Ptr
= wcschr (lpArguments
, L
' ');
280 DPRINT ("Ptr %p lpArguments %p\n", Ptr
, lpArguments
);
283 dwLength
= (DWORD
)(Ptr
- lpArguments
);
284 DPRINT ("dwLength %lu\n", dwLength
);
285 memcpy (szCommand
, lpArguments
, dwLength
* sizeof(WCHAR
));
286 szCommand
[dwLength
] = 0;
288 wcscpy (szArguments
, Ptr
);
292 wcscpy (szCommand
, lpArguments
);
295 DPRINT ("szCommand: '%S'\n", szCommand
);
296 DPRINT ("szArguments: '%S'\n", szArguments
);
298 /* Dynamically load ole32.dll */
299 if (!LoadDynamicImports(&DynOle32
, &Ole32
))
301 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
305 Ole32
.fn
.CoInitialize(NULL
);
307 hr
= Ole32
.fn
.CoCreateInstance(&CLSID_ShellLink
,
309 CLSCTX_INPROC_SERVER
,
314 Ole32
.fn
.CoUninitialize();
315 UnloadDynamicImports(&Ole32
);
319 hr
= psl
->lpVtbl
->QueryInterface(psl
,
324 psl
->lpVtbl
->SetDescription(psl
,
327 psl
->lpVtbl
->SetPath(psl
,
330 psl
->lpVtbl
->SetArguments(psl
,
333 psl
->lpVtbl
->SetIconLocation(psl
,
337 if (lpWorkingDirectory
!= NULL
)
339 psl
->lpVtbl
->SetWorkingDirectory(psl
,
344 psl
->lpVtbl
->SetWorkingDirectory(psl
,
345 L
"%HOMEDRIVE%%HOMEPATH%");
348 psl
->lpVtbl
->SetHotkey(psl
,
351 psl
->lpVtbl
->SetShowCmd(psl
,
354 hr
= ppf
->lpVtbl
->Save(ppf
,
360 ppf
->lpVtbl
->Release(ppf
);
363 psl
->lpVtbl
->Release(psl
);
365 Ole32
.fn
.CoUninitialize();
367 UnloadDynamicImports(&Ole32
);
369 DPRINT ("AddDesktopItemW() done\n");
376 DeleteDesktopItemA (BOOL bCommonItem
,
379 UNICODE_STRING ItemName
;
383 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
385 if (!NT_SUCCESS(Status
))
387 SetLastError (RtlNtStatusToDosError (Status
));
391 bResult
= DeleteDesktopItemW(bCommonItem
,
394 RtlFreeUnicodeString(&ItemName
);
401 DeleteDesktopItemW (BOOL bCommonItem
,
404 WCHAR szLinkPath
[MAX_PATH
];
406 DPRINT ("DeleteDesktopItemW() called\n");
408 if (!GetDesktopPath (bCommonItem
, szLinkPath
))
410 DPRINT1 ("GetDesktopPath() failed\n");
414 wcscat (szLinkPath
, L
"\\");
415 wcscat (szLinkPath
, lpItemName
);
416 wcscat (szLinkPath
, L
".lnk");
417 DPRINT ("Link path: '%S'\n", szLinkPath
);
419 return DeleteFileW (szLinkPath
);
424 CreateGroupA (LPCSTR lpGroupName
,
427 UNICODE_STRING GroupName
;
431 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
433 if (!NT_SUCCESS(Status
))
435 SetLastError (RtlNtStatusToDosError (Status
));
439 bResult
= CreateGroupW(GroupName
.Buffer
, bCommonGroup
);
441 RtlFreeUnicodeString(&GroupName
);
448 CreateGroupW (LPCWSTR lpGroupName
,
451 WCHAR szGroupPath
[MAX_PATH
];
453 DPRINT1 ("CreateGroupW() called\n");
455 if (lpGroupName
== NULL
|| *lpGroupName
== 0)
458 if (!GetProgramsPath (bCommonGroup
, szGroupPath
))
460 DPRINT1 ("GetProgramsPath() failed\n");
463 DPRINT1 ("Programs path: '%S'\n", szGroupPath
);
465 wcscat (szGroupPath
, L
"\\");
466 wcscat (szGroupPath
, lpGroupName
);
467 DPRINT1 ("Group path: '%S'\n", szGroupPath
);
469 /* Create directory path */
470 if (!CreateDirectoryPath (szGroupPath
, NULL
))
473 /* FIXME: Notify the shell */
475 DPRINT1 ("CreateGroupW() done\n");
482 DeleteGroupA (LPCSTR lpGroupName
,
485 UNICODE_STRING GroupName
;
489 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
491 if (!NT_SUCCESS(Status
))
493 SetLastError (RtlNtStatusToDosError (Status
));
497 bResult
= DeleteGroupW(GroupName
.Buffer
, bCommonGroup
);
499 RtlFreeUnicodeString(&GroupName
);
506 DeleteGroupW (LPCWSTR lpGroupName
,
509 WCHAR szGroupPath
[MAX_PATH
];
511 DPRINT ("DeleteGroupW() called\n");
513 if (lpGroupName
== NULL
|| *lpGroupName
== 0)
516 if (!GetProgramsPath (bCommonGroup
, szGroupPath
))
518 DPRINT1 ("GetProgramsPath() failed\n");
521 DPRINT ("Programs path: '%S'\n", szGroupPath
);
523 wcscat (szGroupPath
, L
"\\");
524 wcscat (szGroupPath
, lpGroupName
);
525 DPRINT ("Group path: '%S'\n", szGroupPath
);
527 /* Remove directory path */
528 if (!RemoveDirectoryPath (szGroupPath
))
531 /* FIXME: Notify the shell */
533 DPRINT ("DeleteGroupW() done\n");
540 AddItemA (LPCSTR lpGroupName
, /* Optional */
544 LPCSTR lpIconLocation
,
546 LPCSTR lpWorkingDirectory
, /* Optional */
550 UNICODE_STRING GroupName
;
551 UNICODE_STRING ItemName
;
552 UNICODE_STRING Arguments
;
553 UNICODE_STRING IconLocation
;
554 UNICODE_STRING WorkingDirectory
;
558 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
560 if (!NT_SUCCESS(Status
))
562 SetLastError (RtlNtStatusToDosError (Status
));
566 Status
= RtlCreateUnicodeStringFromAsciiz(&Arguments
,
568 if (!NT_SUCCESS(Status
))
570 RtlFreeUnicodeString(&ItemName
);
571 SetLastError (RtlNtStatusToDosError (Status
));
575 Status
= RtlCreateUnicodeStringFromAsciiz(&IconLocation
,
576 (LPSTR
)lpIconLocation
);
577 if (!NT_SUCCESS(Status
))
579 RtlFreeUnicodeString(&Arguments
);
580 RtlFreeUnicodeString(&ItemName
);
581 SetLastError (RtlNtStatusToDosError (Status
));
585 if (lpGroupName
!= NULL
)
587 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
589 if (!NT_SUCCESS(Status
))
591 RtlFreeUnicodeString(&IconLocation
);
592 RtlFreeUnicodeString(&Arguments
);
593 RtlFreeUnicodeString(&ItemName
);
594 SetLastError (RtlNtStatusToDosError (Status
));
599 if (lpWorkingDirectory
!= NULL
)
601 Status
= RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory
,
602 (LPSTR
)lpWorkingDirectory
);
603 if (!NT_SUCCESS(Status
))
605 if (lpGroupName
!= NULL
)
607 RtlFreeUnicodeString(&GroupName
);
609 RtlFreeUnicodeString(&IconLocation
);
610 RtlFreeUnicodeString(&Arguments
);
611 RtlFreeUnicodeString(&ItemName
);
612 SetLastError (RtlNtStatusToDosError (Status
));
617 bResult
= AddItemW((lpGroupName
!= NULL
) ? GroupName
.Buffer
: NULL
,
623 (lpWorkingDirectory
!= NULL
) ? WorkingDirectory
.Buffer
: NULL
,
627 if (lpGroupName
!= NULL
)
629 RtlFreeUnicodeString(&GroupName
);
632 if (lpWorkingDirectory
!= NULL
)
634 RtlFreeUnicodeString(&WorkingDirectory
);
637 RtlFreeUnicodeString(&IconLocation
);
638 RtlFreeUnicodeString(&Arguments
);
639 RtlFreeUnicodeString(&ItemName
);
646 AddItemW (LPCWSTR lpGroupName
, /* Optional */
650 LPCWSTR lpIconLocation
,
652 LPCWSTR lpWorkingDirectory
, /* Optional */
657 WCHAR szLinkPath
[MAX_PATH
];
658 WCHAR szArguments
[MAX_PATH
];
659 WCHAR szCommand
[MAX_PATH
];
660 WIN32_FIND_DATAW FindData
;
669 DPRINT ("AddItemW() called\n");
673 if (!GetProgramsPath (bCommonGroup
, szLinkPath
))
675 DPRINT1 ("GetProgramsPath() failed\n");
679 DPRINT ("Programs path: '%S'\n", szLinkPath
);
681 if (lpGroupName
!= NULL
&& *lpGroupName
!= 0)
683 wcscat (szLinkPath
, L
"\\");
684 wcscat (szLinkPath
, lpGroupName
);
686 /* Make sure the path exists */
687 hFind
= FindFirstFileW (szLinkPath
,
689 if (hFind
== INVALID_HANDLE_VALUE
)
691 DPRINT ("'%S' does not exist\n", szLinkPath
);
692 if (!CreateGroupW (lpGroupName
,
698 DPRINT ("'%S' exists\n", szLinkPath
);
703 wcscat (szLinkPath
, L
"\\");
704 wcscat (szLinkPath
, lpItemName
);
705 wcscat (szLinkPath
, L
".lnk");
706 DPRINT ("Link path: '%S'\n", szLinkPath
);
708 /* Split 'lpArguments' string into command and arguments */
709 Ptr
= wcschr (lpArguments
, L
' ');
710 DPRINT ("Ptr %p lpArguments %p\n", Ptr
, lpArguments
);
713 dwLength
= (DWORD
)(Ptr
- lpArguments
);
714 DPRINT ("dwLength %lu\n", dwLength
);
715 memcpy (szCommand
, lpArguments
, dwLength
* sizeof(WCHAR
));
716 szCommand
[dwLength
] = 0;
718 wcscpy (szArguments
, Ptr
);
722 wcscpy (szCommand
, lpArguments
);
725 DPRINT ("szCommand: '%S'\n", szCommand
);
726 DPRINT ("szArguments: '%S'\n", szArguments
);
728 /* Dynamically load ole32.dll */
729 if (!LoadDynamicImports(&DynOle32
, &Ole32
))
731 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
735 Ole32
.fn
.CoInitialize(NULL
);
737 hr
= Ole32
.fn
.CoCreateInstance(&CLSID_ShellLink
,
739 CLSCTX_INPROC_SERVER
,
744 Ole32
.fn
.CoUninitialize();
745 UnloadDynamicImports(&Ole32
);
749 hr
= psl
->lpVtbl
->QueryInterface(psl
,
754 psl
->lpVtbl
->SetDescription(psl
,
757 psl
->lpVtbl
->SetPath(psl
,
760 psl
->lpVtbl
->SetArguments(psl
,
763 psl
->lpVtbl
->SetIconLocation(psl
,
767 if (lpWorkingDirectory
!= NULL
)
769 psl
->lpVtbl
->SetWorkingDirectory(psl
,
774 psl
->lpVtbl
->SetWorkingDirectory(psl
,
775 L
"%HOMEDRIVE%%HOMEPATH%");
778 psl
->lpVtbl
->SetHotkey(psl
,
781 psl
->lpVtbl
->SetShowCmd(psl
,
784 hr
= ppf
->lpVtbl
->Save(ppf
,
790 ppf
->lpVtbl
->Release(ppf
);
793 psl
->lpVtbl
->Release(psl
);
795 Ole32
.fn
.CoUninitialize();
796 UnloadDynamicImports(&Ole32
);
798 DPRINT ("AddItemW() done\n");
805 DeleteItemA (LPCSTR lpGroupName
, /* Optional */
810 UNICODE_STRING GroupName
;
811 UNICODE_STRING ItemName
;
815 if (lpGroupName
!= NULL
)
817 Status
= RtlCreateUnicodeStringFromAsciiz(&GroupName
,
819 if (!NT_SUCCESS(Status
))
821 SetLastError (RtlNtStatusToDosError (Status
));
826 Status
= RtlCreateUnicodeStringFromAsciiz(&ItemName
,
828 if (!NT_SUCCESS(Status
))
830 if (lpGroupName
!= NULL
)
832 RtlFreeUnicodeString(&GroupName
);
835 SetLastError (RtlNtStatusToDosError (Status
));
839 bResult
= DeleteItemW((lpGroupName
!= NULL
) ? GroupName
.Buffer
: NULL
,
844 RtlFreeUnicodeString(&ItemName
);
845 if (lpGroupName
!= NULL
)
847 RtlFreeUnicodeString(&GroupName
);
855 DeleteItemW (LPCWSTR lpGroupName
, /* Optional */
860 WCHAR szItemPath
[MAX_PATH
];
863 DPRINT ("DeleteItemW() called\n");
865 if (!GetProgramsPath (bCommonGroup
, szItemPath
))
867 DPRINT1 ("GetProgramsPath() failed\n");
870 DPRINT ("Programs path: '%S'\n", szItemPath
);
872 if (lpGroupName
!= NULL
&& *lpGroupName
!= 0)
874 wcscat (szItemPath
, L
"\\");
875 wcscat (szItemPath
, lpGroupName
);
878 wcscat (szItemPath
, L
"\\");
879 wcscat (szItemPath
, lpItemName
);
880 wcscat (szItemPath
, L
".lnk");
881 DPRINT ("Item path: '%S'\n", szItemPath
);
883 if (!DeleteFileW (szItemPath
))
886 /* FIXME: Notify the shell */
890 Ptr
= wcsrchr (szItemPath
, L
'\\');
895 DPRINT ("Item path: '%S'\n", szItemPath
);
896 if (RemoveDirectoryW (szItemPath
))
898 /* FIXME: Notify the shell */
902 DPRINT ("DeleteItemW() done\n");