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 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.
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
34 /* FUNCTIONS ***************************************************************/
38 GetDesktopPath(BOOL bCommonPath
,
41 WCHAR szPath
[MAX_PATH
];
47 DPRINT("GetDesktopPath() called\n");
49 Error
= RegOpenKeyExW(HKEY_CURRENT_USER
,
50 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
54 if (Error
!= ERROR_SUCCESS
)
56 DPRINT1("RegOpenKeyExW() failed\n");
57 SetLastError((DWORD
)Error
);
61 dwLength
= MAX_PATH
* sizeof(WCHAR
);
62 Error
= RegQueryValueExW(hKey
,
63 bCommonPath
? L
"Common Desktop" : L
"Desktop",
68 if (Error
!= ERROR_SUCCESS
)
70 DPRINT1("RegQueryValueExW() failed\n");
72 SetLastError((DWORD
)Error
);
78 if (dwType
== REG_EXPAND_SZ
)
80 ExpandEnvironmentStringsW(szPath
,
86 wcscpy(lpDesktopPath
, szPath
);
89 DPRINT("GetDesktopPath() done\n");
97 GetProgramsPath(BOOL bCommonPath
,
98 LPWSTR lpProgramsPath
)
100 WCHAR szPath
[MAX_PATH
];
106 DPRINT("GetProgramsPath() called\n");
108 Error
= RegOpenKeyExW(HKEY_CURRENT_USER
,
109 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
113 if (Error
!= ERROR_SUCCESS
)
115 DPRINT1("RegOpenKeyExW() failed\n");
116 SetLastError((DWORD
)Error
);
120 dwLength
= MAX_PATH
* sizeof(WCHAR
);
121 Error
= RegQueryValueExW(hKey
,
122 bCommonPath
? L
"Common Programs" : L
"Programs",
127 if (Error
!= ERROR_SUCCESS
)
129 DPRINT1("RegQueryValueExW() failed\n");
131 SetLastError((DWORD
)Error
);
137 if (dwType
== REG_EXPAND_SZ
)
139 ExpandEnvironmentStringsW(szPath
,
145 wcscpy(lpProgramsPath
,
149 DPRINT("GetProgramsPath() done\n");
157 AddDesktopItemA(BOOL bCommonItem
,
160 LPCSTR lpIconLocation
,
162 LPCSTR lpWorkingDirectory
, /* Optional */
166 UNICODE_STRING ItemName
;
167 UNICODE_STRING Arguments
;
168 UNICODE_STRING IconLocation
;
169 UNICODE_STRING WorkingDirectory
;
172 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName
,
175 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
179 if (!RtlCreateUnicodeStringFromAsciiz(&Arguments
,
182 RtlFreeUnicodeString(&ItemName
);
183 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
187 if (!RtlCreateUnicodeStringFromAsciiz(&IconLocation
,
188 (LPSTR
)lpIconLocation
))
190 RtlFreeUnicodeString(&Arguments
);
191 RtlFreeUnicodeString(&ItemName
);
192 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
196 if (lpWorkingDirectory
!= NULL
)
198 if (!RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory
,
199 (LPSTR
)lpWorkingDirectory
))
201 RtlFreeUnicodeString(&IconLocation
);
202 RtlFreeUnicodeString(&Arguments
);
203 RtlFreeUnicodeString(&ItemName
);
204 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
209 bResult
= AddDesktopItemW(bCommonItem
,
214 (lpWorkingDirectory
!= NULL
) ? WorkingDirectory
.Buffer
: NULL
,
218 if (lpWorkingDirectory
!= NULL
)
220 RtlFreeUnicodeString(&WorkingDirectory
);
223 RtlFreeUnicodeString(&IconLocation
);
224 RtlFreeUnicodeString(&Arguments
);
225 RtlFreeUnicodeString(&ItemName
);
233 AddDesktopItemW(BOOL bCommonDesktop
,
236 LPCWSTR lpIconLocation
,
238 LPCWSTR lpWorkingDirectory
, /* Optional */
243 WCHAR szLinkPath
[MAX_PATH
];
244 WCHAR szArguments
[MAX_PATH
];
245 WCHAR szCommand
[MAX_PATH
];
246 WIN32_FIND_DATAW FindData
;
255 DPRINT("AddDesktopItemW() called\n");
259 if (!GetDesktopPath(bCommonDesktop
, szLinkPath
))
261 DPRINT1("GetDesktopPath() failed\n");
264 DPRINT("Desktop path: '%S'\n", szLinkPath
);
266 /* Make sure the path exists */
267 hFind
= FindFirstFileW(szLinkPath
,
269 if (hFind
== INVALID_HANDLE_VALUE
)
271 DPRINT("'%S' does not exist\n", szLinkPath
);
273 /* Create directory path */
274 if (!CreateDirectoryPath(szLinkPath
, NULL
))
279 DPRINT("'%S' exists\n", szLinkPath
);
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
);
289 /* Split 'lpArguments' string into command and arguments */
290 Ptr
= wcschr(lpArguments
, L
' ');
291 DPRINT("Ptr %p lpArguments %p\n", Ptr
, lpArguments
);
294 dwLength
= (DWORD
)(Ptr
- lpArguments
);
295 DPRINT("dwLength %lu\n", dwLength
);
296 memcpy(szCommand
, lpArguments
, dwLength
* sizeof(WCHAR
));
297 szCommand
[dwLength
] = 0;
299 wcscpy(szArguments
, Ptr
);
303 wcscpy(szCommand
, lpArguments
);
306 DPRINT("szCommand: '%S'\n", szCommand
);
307 DPRINT("szArguments: '%S'\n", szArguments
);
309 /* Dynamically load ole32.dll */
310 if (!LoadDynamicImports(&DynOle32
, &Ole32
))
312 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
316 Ole32
.fn
.CoInitialize(NULL
);
318 hr
= Ole32
.fn
.CoCreateInstance(&CLSID_ShellLink
,
320 CLSCTX_INPROC_SERVER
,
325 Ole32
.fn
.CoUninitialize();
326 UnloadDynamicImports(&Ole32
);
330 hr
= psl
->lpVtbl
->QueryInterface(psl
,
335 psl
->lpVtbl
->SetDescription(psl
,
338 psl
->lpVtbl
->SetPath(psl
,
341 psl
->lpVtbl
->SetArguments(psl
,
344 psl
->lpVtbl
->SetIconLocation(psl
,
348 if (lpWorkingDirectory
!= NULL
)
350 psl
->lpVtbl
->SetWorkingDirectory(psl
,
355 psl
->lpVtbl
->SetWorkingDirectory(psl
,
356 L
"%HOMEDRIVE%%HOMEPATH%");
359 psl
->lpVtbl
->SetHotkey(psl
,
362 psl
->lpVtbl
->SetShowCmd(psl
,
365 hr
= ppf
->lpVtbl
->Save(ppf
,
371 ppf
->lpVtbl
->Release(ppf
);
374 psl
->lpVtbl
->Release(psl
);
376 Ole32
.fn
.CoUninitialize();
378 UnloadDynamicImports(&Ole32
);
380 DPRINT("AddDesktopItemW() done\n");
388 DeleteDesktopItemA(BOOL bCommonItem
,
391 UNICODE_STRING ItemName
;
394 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName
,
397 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
401 bResult
= DeleteDesktopItemW(bCommonItem
,
404 RtlFreeUnicodeString(&ItemName
);
412 DeleteDesktopItemW(BOOL bCommonItem
,
415 WCHAR szLinkPath
[MAX_PATH
];
417 DPRINT("DeleteDesktopItemW() called\n");
419 if (!GetDesktopPath(bCommonItem
, szLinkPath
))
421 DPRINT1("GetDesktopPath() failed\n");
425 wcscat(szLinkPath
, L
"\\");
426 wcscat(szLinkPath
, lpItemName
);
427 wcscat(szLinkPath
, L
".lnk");
428 DPRINT("Link path: '%S'\n", szLinkPath
);
430 return DeleteFileW (szLinkPath
);
436 CreateGroupA(LPCSTR lpGroupName
,
439 UNICODE_STRING GroupName
;
442 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName
,
445 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
449 bResult
= CreateGroupW(GroupName
.Buffer
, bCommonGroup
);
451 RtlFreeUnicodeString(&GroupName
);
459 CreateGroupW(LPCWSTR lpGroupName
,
462 WCHAR szGroupPath
[MAX_PATH
];
464 DPRINT1("CreateGroupW() called\n");
466 if (lpGroupName
== NULL
|| *lpGroupName
== 0)
469 if (!GetProgramsPath(bCommonGroup
, szGroupPath
))
471 DPRINT1("GetProgramsPath() failed\n");
474 DPRINT1("Programs path: '%S'\n", szGroupPath
);
476 wcscat(szGroupPath
, L
"\\");
477 wcscat(szGroupPath
, lpGroupName
);
478 DPRINT1("Group path: '%S'\n", szGroupPath
);
480 /* Create directory path */
481 if (!CreateDirectoryPath (szGroupPath
, NULL
))
484 /* FIXME: Notify the shell */
486 DPRINT1("CreateGroupW() done\n");
494 DeleteGroupA(LPCSTR lpGroupName
,
497 UNICODE_STRING GroupName
;
500 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName
,
503 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
507 bResult
= DeleteGroupW(GroupName
.Buffer
, bCommonGroup
);
509 RtlFreeUnicodeString(&GroupName
);
517 DeleteGroupW(LPCWSTR lpGroupName
,
520 WCHAR szGroupPath
[MAX_PATH
];
522 DPRINT("DeleteGroupW() called\n");
524 if (lpGroupName
== NULL
|| *lpGroupName
== 0)
527 if (!GetProgramsPath(bCommonGroup
, szGroupPath
))
529 DPRINT1("GetProgramsPath() failed\n");
532 DPRINT("Programs path: '%S'\n", szGroupPath
);
534 wcscat(szGroupPath
, L
"\\");
535 wcscat(szGroupPath
, lpGroupName
);
536 DPRINT("Group path: '%S'\n", szGroupPath
);
538 /* Remove directory path */
539 if (!RemoveDirectoryPath (szGroupPath
))
542 /* FIXME: Notify the shell */
544 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
;
569 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName
,
572 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
576 if (!RtlCreateUnicodeStringFromAsciiz(&Arguments
,
579 RtlFreeUnicodeString(&ItemName
);
580 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
584 if (!RtlCreateUnicodeStringFromAsciiz(&IconLocation
,
585 (LPSTR
)lpIconLocation
))
587 RtlFreeUnicodeString(&Arguments
);
588 RtlFreeUnicodeString(&ItemName
);
589 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
593 if (lpGroupName
!= NULL
)
595 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName
,
598 RtlFreeUnicodeString(&IconLocation
);
599 RtlFreeUnicodeString(&Arguments
);
600 RtlFreeUnicodeString(&ItemName
);
601 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
606 if (lpWorkingDirectory
!= NULL
)
608 if (!RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory
,
609 (LPSTR
)lpWorkingDirectory
))
611 if (lpGroupName
!= NULL
)
613 RtlFreeUnicodeString(&GroupName
);
615 RtlFreeUnicodeString(&IconLocation
);
616 RtlFreeUnicodeString(&Arguments
);
617 RtlFreeUnicodeString(&ItemName
);
618 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
623 bResult
= AddItemW((lpGroupName
!= NULL
) ? GroupName
.Buffer
: NULL
,
629 (lpWorkingDirectory
!= NULL
) ? WorkingDirectory
.Buffer
: NULL
,
633 if (lpGroupName
!= NULL
)
635 RtlFreeUnicodeString(&GroupName
);
638 if (lpWorkingDirectory
!= NULL
)
640 RtlFreeUnicodeString(&WorkingDirectory
);
643 RtlFreeUnicodeString(&IconLocation
);
644 RtlFreeUnicodeString(&Arguments
);
645 RtlFreeUnicodeString(&ItemName
);
653 AddItemW(LPCWSTR lpGroupName
, /* Optional */
657 LPCWSTR lpIconLocation
,
659 LPCWSTR lpWorkingDirectory
, /* Optional */
664 WCHAR szLinkPath
[MAX_PATH
];
665 WCHAR szArguments
[MAX_PATH
];
666 WCHAR szCommand
[MAX_PATH
];
667 WIN32_FIND_DATAW FindData
;
676 DPRINT("AddItemW() called\n");
680 if (!GetProgramsPath(bCommonGroup
, szLinkPath
))
682 DPRINT1("GetProgramsPath() failed\n");
686 DPRINT("Programs path: '%S'\n", szLinkPath
);
688 if (lpGroupName
!= NULL
&& *lpGroupName
!= 0)
690 wcscat(szLinkPath
, L
"\\");
691 wcscat(szLinkPath
, lpGroupName
);
693 /* Make sure the path exists */
694 hFind
= FindFirstFileW(szLinkPath
,
696 if (hFind
== INVALID_HANDLE_VALUE
)
698 DPRINT("'%S' does not exist\n", szLinkPath
);
699 if (!CreateGroupW(lpGroupName
,
705 DPRINT("'%S' exists\n", szLinkPath
);
710 wcscat(szLinkPath
, L
"\\");
711 wcscat(szLinkPath
, lpItemName
);
712 wcscat(szLinkPath
, L
".lnk");
713 DPRINT("Link path: '%S'\n", szLinkPath
);
715 /* Split 'lpArguments' string into command and arguments */
716 Ptr
= wcschr(lpArguments
, L
' ');
717 DPRINT("Ptr %p lpArguments %p\n", Ptr
, lpArguments
);
720 dwLength
= (DWORD
)(Ptr
- lpArguments
);
721 DPRINT("dwLength %lu\n", dwLength
);
722 memcpy(szCommand
, lpArguments
, dwLength
* sizeof(WCHAR
));
723 szCommand
[dwLength
] = 0;
725 wcscpy(szArguments
, Ptr
);
729 wcscpy(szCommand
, lpArguments
);
732 DPRINT("szCommand: '%S'\n", szCommand
);
733 DPRINT("szArguments: '%S'\n", szArguments
);
735 /* Dynamically load ole32.dll */
736 if (!LoadDynamicImports(&DynOle32
, &Ole32
))
738 DPRINT1("USERENV: Unable to load OLE32.DLL\n");
742 Ole32
.fn
.CoInitialize(NULL
);
744 hr
= Ole32
.fn
.CoCreateInstance(&CLSID_ShellLink
,
746 CLSCTX_INPROC_SERVER
,
751 Ole32
.fn
.CoUninitialize();
752 UnloadDynamicImports(&Ole32
);
756 hr
= psl
->lpVtbl
->QueryInterface(psl
,
761 psl
->lpVtbl
->SetDescription(psl
,
764 psl
->lpVtbl
->SetPath(psl
,
767 psl
->lpVtbl
->SetArguments(psl
,
770 psl
->lpVtbl
->SetIconLocation(psl
,
774 if (lpWorkingDirectory
!= NULL
)
776 psl
->lpVtbl
->SetWorkingDirectory(psl
,
781 psl
->lpVtbl
->SetWorkingDirectory(psl
,
782 L
"%HOMEDRIVE%%HOMEPATH%");
785 psl
->lpVtbl
->SetHotkey(psl
,
788 psl
->lpVtbl
->SetShowCmd(psl
,
791 hr
= ppf
->lpVtbl
->Save(ppf
,
797 ppf
->lpVtbl
->Release(ppf
);
800 psl
->lpVtbl
->Release(psl
);
802 Ole32
.fn
.CoUninitialize();
803 UnloadDynamicImports(&Ole32
);
805 DPRINT("AddItemW() done\n");
813 DeleteItemA(LPCSTR lpGroupName
, /* Optional */
818 UNICODE_STRING GroupName
;
819 UNICODE_STRING ItemName
;
822 if (lpGroupName
!= NULL
)
824 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName
,
827 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
832 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName
,
835 if (lpGroupName
!= NULL
)
837 RtlFreeUnicodeString(&GroupName
);
840 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
844 bResult
= DeleteItemW((lpGroupName
!= NULL
) ? GroupName
.Buffer
: NULL
,
849 RtlFreeUnicodeString(&ItemName
);
850 if (lpGroupName
!= NULL
)
852 RtlFreeUnicodeString(&GroupName
);
861 DeleteItemW(LPCWSTR lpGroupName
, /* Optional */
866 WCHAR szItemPath
[MAX_PATH
];
869 DPRINT("DeleteItemW() called\n");
871 if (!GetProgramsPath(bCommonGroup
, szItemPath
))
873 DPRINT1("GetProgramsPath() failed\n");
876 DPRINT("Programs path: '%S'\n", szItemPath
);
878 if (lpGroupName
!= NULL
&& *lpGroupName
!= 0)
880 wcscat(szItemPath
, L
"\\");
881 wcscat(szItemPath
, lpGroupName
);
884 wcscat(szItemPath
, L
"\\");
885 wcscat(szItemPath
, lpItemName
);
886 wcscat(szItemPath
, L
".lnk");
887 DPRINT("Item path: '%S'\n", szItemPath
);
889 if (!DeleteFileW(szItemPath
))
892 /* FIXME: Notify the shell */
896 Ptr
= wcsrchr(szItemPath
, L
'\\');
901 DPRINT("Item path: '%S'\n", szItemPath
);
902 if (RemoveDirectoryW(szItemPath
))
904 /* FIXME: Notify the shell */
908 DPRINT("DeleteItemW() done\n");