mirror of
https://github.com/reactos/reactos.git
synced 2024-08-23 03:42:40 +00:00
914 lines
23 KiB
C
914 lines
23 KiB
C
/*
|
|
* ReactOS kernel
|
|
* Copyright (C) 2004 ReactOS Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS system libraries
|
|
* FILE: dll/win32/userenv/desktop.c
|
|
* PURPOSE: Desktop and start menu support functions.
|
|
* PROGRAMMER: Eric Kohl
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <shlobj.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
static
|
|
BOOL
|
|
GetDesktopPath(BOOL bCommonPath,
|
|
LPWSTR lpDesktopPath)
|
|
{
|
|
WCHAR szPath[MAX_PATH];
|
|
DWORD dwLength;
|
|
DWORD dwType;
|
|
HKEY hKey;
|
|
LONG Error;
|
|
|
|
DPRINT("GetDesktopPath() called\n");
|
|
|
|
Error = RegOpenKeyExW(HKEY_CURRENT_USER,
|
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hKey);
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
DPRINT1("RegOpenKeyExW() failed\n");
|
|
SetLastError((DWORD)Error);
|
|
return FALSE;
|
|
}
|
|
|
|
dwLength = MAX_PATH * sizeof(WCHAR);
|
|
Error = RegQueryValueExW(hKey,
|
|
bCommonPath ? L"Common Desktop" : L"Desktop",
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)szPath,
|
|
&dwLength);
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
DPRINT1("RegQueryValueExW() failed\n");
|
|
RegCloseKey(hKey);
|
|
SetLastError((DWORD)Error);
|
|
return FALSE;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
if (dwType == REG_EXPAND_SZ)
|
|
{
|
|
ExpandEnvironmentStringsW(szPath,
|
|
lpDesktopPath,
|
|
MAX_PATH);
|
|
}
|
|
else
|
|
{
|
|
wcscpy(lpDesktopPath, szPath);
|
|
}
|
|
|
|
DPRINT("GetDesktopPath() done\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static
|
|
BOOL
|
|
GetProgramsPath(BOOL bCommonPath,
|
|
LPWSTR lpProgramsPath)
|
|
{
|
|
WCHAR szPath[MAX_PATH];
|
|
DWORD dwLength;
|
|
DWORD dwType;
|
|
HKEY hKey;
|
|
LONG Error;
|
|
|
|
DPRINT("GetProgramsPath() called\n");
|
|
|
|
Error = RegOpenKeyExW(HKEY_CURRENT_USER,
|
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hKey);
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
DPRINT1("RegOpenKeyExW() failed\n");
|
|
SetLastError((DWORD)Error);
|
|
return FALSE;
|
|
}
|
|
|
|
dwLength = MAX_PATH * sizeof(WCHAR);
|
|
Error = RegQueryValueExW(hKey,
|
|
bCommonPath ? L"Common Programs" : L"Programs",
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)szPath,
|
|
&dwLength);
|
|
if (Error != ERROR_SUCCESS)
|
|
{
|
|
DPRINT1("RegQueryValueExW() failed\n");
|
|
RegCloseKey(hKey);
|
|
SetLastError((DWORD)Error);
|
|
return FALSE;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
if (dwType == REG_EXPAND_SZ)
|
|
{
|
|
ExpandEnvironmentStringsW(szPath,
|
|
lpProgramsPath,
|
|
MAX_PATH);
|
|
}
|
|
else
|
|
{
|
|
wcscpy(lpProgramsPath,
|
|
szPath);
|
|
}
|
|
|
|
DPRINT("GetProgramsPath() done\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
AddDesktopItemA(BOOL bCommonItem,
|
|
LPCSTR lpItemName,
|
|
LPCSTR lpArguments,
|
|
LPCSTR lpIconLocation,
|
|
INT iIcon,
|
|
LPCSTR lpWorkingDirectory, /* Optional */
|
|
WORD wHotKey,
|
|
INT iShowCmd)
|
|
{
|
|
UNICODE_STRING ItemName;
|
|
UNICODE_STRING Arguments;
|
|
UNICODE_STRING IconLocation;
|
|
UNICODE_STRING WorkingDirectory;
|
|
BOOL bResult;
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&ItemName,
|
|
(LPSTR)lpItemName))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&Arguments,
|
|
(LPSTR)lpArguments))
|
|
{
|
|
RtlFreeUnicodeString(&ItemName);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&IconLocation,
|
|
(LPSTR)lpIconLocation))
|
|
{
|
|
RtlFreeUnicodeString(&Arguments);
|
|
RtlFreeUnicodeString(&ItemName);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpWorkingDirectory != NULL)
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory,
|
|
(LPSTR)lpWorkingDirectory))
|
|
{
|
|
RtlFreeUnicodeString(&IconLocation);
|
|
RtlFreeUnicodeString(&Arguments);
|
|
RtlFreeUnicodeString(&ItemName);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
bResult = AddDesktopItemW(bCommonItem,
|
|
ItemName.Buffer,
|
|
Arguments.Buffer,
|
|
IconLocation.Buffer,
|
|
iIcon,
|
|
(lpWorkingDirectory != NULL) ? WorkingDirectory.Buffer : NULL,
|
|
wHotKey,
|
|
iShowCmd);
|
|
|
|
if (lpWorkingDirectory != NULL)
|
|
{
|
|
RtlFreeUnicodeString(&WorkingDirectory);
|
|
}
|
|
|
|
RtlFreeUnicodeString(&IconLocation);
|
|
RtlFreeUnicodeString(&Arguments);
|
|
RtlFreeUnicodeString(&ItemName);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
AddDesktopItemW(BOOL bCommonDesktop,
|
|
LPCWSTR lpItemName,
|
|
LPCWSTR lpArguments,
|
|
LPCWSTR lpIconLocation,
|
|
INT iIcon,
|
|
LPCWSTR lpWorkingDirectory, /* Optional */
|
|
WORD wHotKey,
|
|
INT iShowCmd)
|
|
{
|
|
DYN_FUNCS Ole32;
|
|
WCHAR szLinkPath[MAX_PATH];
|
|
WCHAR szArguments[MAX_PATH];
|
|
WCHAR szCommand[MAX_PATH];
|
|
WIN32_FIND_DATAW FindData;
|
|
HANDLE hFind;
|
|
LPWSTR Ptr;
|
|
DWORD dwLength;
|
|
IShellLinkW* psl;
|
|
IPersistFile* ppf;
|
|
HRESULT hr;
|
|
BOOL bResult;
|
|
|
|
DPRINT("AddDesktopItemW() called\n");
|
|
|
|
bResult = FALSE;
|
|
|
|
if (!GetDesktopPath(bCommonDesktop, szLinkPath))
|
|
{
|
|
DPRINT1("GetDesktopPath() failed\n");
|
|
return FALSE;
|
|
}
|
|
DPRINT("Desktop path: '%S'\n", szLinkPath);
|
|
|
|
/* Make sure the path exists */
|
|
hFind = FindFirstFileW(szLinkPath,
|
|
&FindData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
DPRINT("'%S' does not exist\n", szLinkPath);
|
|
|
|
/* Create directory path */
|
|
if (!CreateDirectoryPath(szLinkPath, NULL))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
DPRINT("'%S' exists\n", szLinkPath);
|
|
FindClose(hFind);
|
|
}
|
|
|
|
/* Append backslash, item name and ".lnk" extension */
|
|
wcscat(szLinkPath, L"\\");
|
|
wcscat(szLinkPath, lpItemName);
|
|
wcscat(szLinkPath, L".lnk");
|
|
DPRINT("Link path: '%S'\n", szLinkPath);
|
|
|
|
/* Split 'lpArguments' string into command and arguments */
|
|
Ptr = wcschr(lpArguments, L' ');
|
|
DPRINT("Ptr %p lpArguments %p\n", Ptr, lpArguments);
|
|
if (Ptr != NULL)
|
|
{
|
|
dwLength = (DWORD)(Ptr - lpArguments);
|
|
DPRINT("dwLength %lu\n", dwLength);
|
|
memcpy(szCommand, lpArguments, dwLength * sizeof(WCHAR));
|
|
szCommand[dwLength] = 0;
|
|
Ptr++;
|
|
wcscpy(szArguments, Ptr);
|
|
}
|
|
else
|
|
{
|
|
wcscpy(szCommand, lpArguments);
|
|
szArguments[0] = 0;
|
|
}
|
|
DPRINT("szCommand: '%S'\n", szCommand);
|
|
DPRINT("szArguments: '%S'\n", szArguments);
|
|
|
|
/* Dynamically load ole32.dll */
|
|
if (!LoadDynamicImports(&DynOle32, &Ole32))
|
|
{
|
|
DPRINT1("USERENV: Unable to load OLE32.DLL\n");
|
|
return FALSE;
|
|
}
|
|
|
|
Ole32.fn.CoInitialize(NULL);
|
|
|
|
hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_IShellLinkW,
|
|
(LPVOID*)&psl);
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
Ole32.fn.CoUninitialize();
|
|
UnloadDynamicImports(&Ole32);
|
|
return FALSE;
|
|
}
|
|
|
|
hr = psl->lpVtbl->QueryInterface(psl,
|
|
&IID_IPersistFile,
|
|
(LPVOID*)&ppf);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
psl->lpVtbl->SetDescription(psl,
|
|
lpItemName);
|
|
|
|
psl->lpVtbl->SetPath(psl,
|
|
szCommand);
|
|
|
|
psl->lpVtbl->SetArguments(psl,
|
|
szArguments);
|
|
|
|
psl->lpVtbl->SetIconLocation(psl,
|
|
lpIconLocation,
|
|
iIcon);
|
|
|
|
if (lpWorkingDirectory != NULL)
|
|
{
|
|
psl->lpVtbl->SetWorkingDirectory(psl,
|
|
lpWorkingDirectory);
|
|
}
|
|
else
|
|
{
|
|
psl->lpVtbl->SetWorkingDirectory(psl,
|
|
L"%HOMEDRIVE%%HOMEPATH%");
|
|
}
|
|
|
|
psl->lpVtbl->SetHotkey(psl,
|
|
wHotKey);
|
|
|
|
psl->lpVtbl->SetShowCmd(psl,
|
|
iShowCmd);
|
|
|
|
hr = ppf->lpVtbl->Save(ppf,
|
|
szLinkPath,
|
|
TRUE);
|
|
if (SUCCEEDED(hr))
|
|
bResult = TRUE;
|
|
|
|
ppf->lpVtbl->Release(ppf);
|
|
}
|
|
|
|
psl->lpVtbl->Release(psl);
|
|
|
|
Ole32.fn.CoUninitialize();
|
|
|
|
UnloadDynamicImports(&Ole32);
|
|
|
|
DPRINT("AddDesktopItemW() done\n");
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DeleteDesktopItemA(BOOL bCommonItem,
|
|
LPCSTR lpItemName)
|
|
{
|
|
UNICODE_STRING ItemName;
|
|
BOOL bResult;
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&ItemName,
|
|
(LPSTR)lpItemName))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
bResult = DeleteDesktopItemW(bCommonItem,
|
|
ItemName.Buffer);
|
|
|
|
RtlFreeUnicodeString(&ItemName);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DeleteDesktopItemW(BOOL bCommonItem,
|
|
LPCWSTR lpItemName)
|
|
{
|
|
WCHAR szLinkPath[MAX_PATH];
|
|
|
|
DPRINT("DeleteDesktopItemW() called\n");
|
|
|
|
if (!GetDesktopPath(bCommonItem, szLinkPath))
|
|
{
|
|
DPRINT1("GetDesktopPath() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
wcscat(szLinkPath, L"\\");
|
|
wcscat(szLinkPath, lpItemName);
|
|
wcscat(szLinkPath, L".lnk");
|
|
DPRINT("Link path: '%S'\n", szLinkPath);
|
|
|
|
return DeleteFileW (szLinkPath);
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CreateGroupA(LPCSTR lpGroupName,
|
|
BOOL bCommonGroup)
|
|
{
|
|
UNICODE_STRING GroupName;
|
|
BOOL bResult;
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&GroupName,
|
|
(LPSTR)lpGroupName))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
bResult = CreateGroupW(GroupName.Buffer, bCommonGroup);
|
|
|
|
RtlFreeUnicodeString(&GroupName);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CreateGroupW(LPCWSTR lpGroupName,
|
|
BOOL bCommonGroup)
|
|
{
|
|
WCHAR szGroupPath[MAX_PATH];
|
|
|
|
DPRINT1("CreateGroupW() called\n");
|
|
|
|
if (lpGroupName == NULL || *lpGroupName == 0)
|
|
return TRUE;
|
|
|
|
if (!GetProgramsPath(bCommonGroup, szGroupPath))
|
|
{
|
|
DPRINT1("GetProgramsPath() failed\n");
|
|
return FALSE;
|
|
}
|
|
DPRINT1("Programs path: '%S'\n", szGroupPath);
|
|
|
|
wcscat(szGroupPath, L"\\");
|
|
wcscat(szGroupPath, lpGroupName);
|
|
DPRINT1("Group path: '%S'\n", szGroupPath);
|
|
|
|
/* Create directory path */
|
|
if (!CreateDirectoryPath (szGroupPath, NULL))
|
|
return FALSE;
|
|
|
|
/* FIXME: Notify the shell */
|
|
|
|
DPRINT1("CreateGroupW() done\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DeleteGroupA(LPCSTR lpGroupName,
|
|
BOOL bCommonGroup)
|
|
{
|
|
UNICODE_STRING GroupName;
|
|
BOOL bResult;
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&GroupName,
|
|
(LPSTR)lpGroupName))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
bResult = DeleteGroupW(GroupName.Buffer, bCommonGroup);
|
|
|
|
RtlFreeUnicodeString(&GroupName);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DeleteGroupW(LPCWSTR lpGroupName,
|
|
BOOL bCommonGroup)
|
|
{
|
|
WCHAR szGroupPath[MAX_PATH];
|
|
|
|
DPRINT("DeleteGroupW() called\n");
|
|
|
|
if (lpGroupName == NULL || *lpGroupName == 0)
|
|
return TRUE;
|
|
|
|
if (!GetProgramsPath(bCommonGroup, szGroupPath))
|
|
{
|
|
DPRINT1("GetProgramsPath() failed\n");
|
|
return FALSE;
|
|
}
|
|
DPRINT("Programs path: '%S'\n", szGroupPath);
|
|
|
|
wcscat(szGroupPath, L"\\");
|
|
wcscat(szGroupPath, lpGroupName);
|
|
DPRINT("Group path: '%S'\n", szGroupPath);
|
|
|
|
/* Remove directory path */
|
|
if (!RemoveDirectoryPath (szGroupPath))
|
|
return FALSE;
|
|
|
|
/* FIXME: Notify the shell */
|
|
|
|
DPRINT("DeleteGroupW() done\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
AddItemA(LPCSTR lpGroupName, /* Optional */
|
|
BOOL bCommonGroup,
|
|
LPCSTR lpItemName,
|
|
LPCSTR lpArguments,
|
|
LPCSTR lpIconLocation,
|
|
INT iIcon,
|
|
LPCSTR lpWorkingDirectory, /* Optional */
|
|
WORD wHotKey,
|
|
INT iShowCmd)
|
|
{
|
|
UNICODE_STRING GroupName;
|
|
UNICODE_STRING ItemName;
|
|
UNICODE_STRING Arguments;
|
|
UNICODE_STRING IconLocation;
|
|
UNICODE_STRING WorkingDirectory;
|
|
BOOL bResult;
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&ItemName,
|
|
(LPSTR)lpItemName))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&Arguments,
|
|
(LPSTR)lpArguments))
|
|
{
|
|
RtlFreeUnicodeString(&ItemName);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&IconLocation,
|
|
(LPSTR)lpIconLocation))
|
|
{
|
|
RtlFreeUnicodeString(&Arguments);
|
|
RtlFreeUnicodeString(&ItemName);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpGroupName != NULL)
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&GroupName,
|
|
(LPSTR)lpGroupName))
|
|
{
|
|
RtlFreeUnicodeString(&IconLocation);
|
|
RtlFreeUnicodeString(&Arguments);
|
|
RtlFreeUnicodeString(&ItemName);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (lpWorkingDirectory != NULL)
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory,
|
|
(LPSTR)lpWorkingDirectory))
|
|
{
|
|
if (lpGroupName != NULL)
|
|
{
|
|
RtlFreeUnicodeString(&GroupName);
|
|
}
|
|
RtlFreeUnicodeString(&IconLocation);
|
|
RtlFreeUnicodeString(&Arguments);
|
|
RtlFreeUnicodeString(&ItemName);
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
bResult = AddItemW((lpGroupName != NULL) ? GroupName.Buffer : NULL,
|
|
bCommonGroup,
|
|
ItemName.Buffer,
|
|
Arguments.Buffer,
|
|
IconLocation.Buffer,
|
|
iIcon,
|
|
(lpWorkingDirectory != NULL) ? WorkingDirectory.Buffer : NULL,
|
|
wHotKey,
|
|
iShowCmd);
|
|
|
|
if (lpGroupName != NULL)
|
|
{
|
|
RtlFreeUnicodeString(&GroupName);
|
|
}
|
|
|
|
if (lpWorkingDirectory != NULL)
|
|
{
|
|
RtlFreeUnicodeString(&WorkingDirectory);
|
|
}
|
|
|
|
RtlFreeUnicodeString(&IconLocation);
|
|
RtlFreeUnicodeString(&Arguments);
|
|
RtlFreeUnicodeString(&ItemName);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
AddItemW(LPCWSTR lpGroupName, /* Optional */
|
|
BOOL bCommonGroup,
|
|
LPCWSTR lpItemName,
|
|
LPCWSTR lpArguments,
|
|
LPCWSTR lpIconLocation,
|
|
INT iIcon,
|
|
LPCWSTR lpWorkingDirectory, /* Optional */
|
|
WORD wHotKey,
|
|
INT iShowCmd)
|
|
{
|
|
DYN_FUNCS Ole32;
|
|
WCHAR szLinkPath[MAX_PATH];
|
|
WCHAR szArguments[MAX_PATH];
|
|
WCHAR szCommand[MAX_PATH];
|
|
WIN32_FIND_DATAW FindData;
|
|
HANDLE hFind;
|
|
LPWSTR Ptr;
|
|
DWORD dwLength;
|
|
IShellLinkW* psl;
|
|
IPersistFile* ppf;
|
|
HRESULT hr;
|
|
BOOL bResult;
|
|
|
|
DPRINT("AddItemW() called\n");
|
|
|
|
bResult = FALSE;
|
|
|
|
if (!GetProgramsPath(bCommonGroup, szLinkPath))
|
|
{
|
|
DPRINT1("GetProgramsPath() failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
DPRINT("Programs path: '%S'\n", szLinkPath);
|
|
|
|
if (lpGroupName != NULL && *lpGroupName != 0)
|
|
{
|
|
wcscat(szLinkPath, L"\\");
|
|
wcscat(szLinkPath, lpGroupName);
|
|
|
|
/* Make sure the path exists */
|
|
hFind = FindFirstFileW(szLinkPath,
|
|
&FindData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
DPRINT("'%S' does not exist\n", szLinkPath);
|
|
if (!CreateGroupW(lpGroupName,
|
|
bCommonGroup))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
DPRINT("'%S' exists\n", szLinkPath);
|
|
FindClose(hFind);
|
|
}
|
|
}
|
|
|
|
wcscat(szLinkPath, L"\\");
|
|
wcscat(szLinkPath, lpItemName);
|
|
wcscat(szLinkPath, L".lnk");
|
|
DPRINT("Link path: '%S'\n", szLinkPath);
|
|
|
|
/* Split 'lpArguments' string into command and arguments */
|
|
Ptr = wcschr(lpArguments, L' ');
|
|
DPRINT("Ptr %p lpArguments %p\n", Ptr, lpArguments);
|
|
if (Ptr != NULL)
|
|
{
|
|
dwLength = (DWORD)(Ptr - lpArguments);
|
|
DPRINT("dwLength %lu\n", dwLength);
|
|
memcpy(szCommand, lpArguments, dwLength * sizeof(WCHAR));
|
|
szCommand[dwLength] = 0;
|
|
Ptr++;
|
|
wcscpy(szArguments, Ptr);
|
|
}
|
|
else
|
|
{
|
|
wcscpy(szCommand, lpArguments);
|
|
szArguments[0] = 0;
|
|
}
|
|
DPRINT("szCommand: '%S'\n", szCommand);
|
|
DPRINT("szArguments: '%S'\n", szArguments);
|
|
|
|
/* Dynamically load ole32.dll */
|
|
if (!LoadDynamicImports(&DynOle32, &Ole32))
|
|
{
|
|
DPRINT1("USERENV: Unable to load OLE32.DLL\n");
|
|
return FALSE;
|
|
}
|
|
|
|
Ole32.fn.CoInitialize(NULL);
|
|
|
|
hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_IShellLinkW,
|
|
(LPVOID*)&psl);
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
Ole32.fn.CoUninitialize();
|
|
UnloadDynamicImports(&Ole32);
|
|
return FALSE;
|
|
}
|
|
|
|
hr = psl->lpVtbl->QueryInterface(psl,
|
|
&IID_IPersistFile,
|
|
(LPVOID*)&ppf);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
psl->lpVtbl->SetDescription(psl,
|
|
lpItemName);
|
|
|
|
psl->lpVtbl->SetPath(psl,
|
|
szCommand);
|
|
|
|
psl->lpVtbl->SetArguments(psl,
|
|
szArguments);
|
|
|
|
psl->lpVtbl->SetIconLocation(psl,
|
|
lpIconLocation,
|
|
iIcon);
|
|
|
|
if (lpWorkingDirectory != NULL)
|
|
{
|
|
psl->lpVtbl->SetWorkingDirectory(psl,
|
|
lpWorkingDirectory);
|
|
}
|
|
else
|
|
{
|
|
psl->lpVtbl->SetWorkingDirectory(psl,
|
|
L"%HOMEDRIVE%%HOMEPATH%");
|
|
}
|
|
|
|
psl->lpVtbl->SetHotkey(psl,
|
|
wHotKey);
|
|
|
|
psl->lpVtbl->SetShowCmd(psl,
|
|
iShowCmd);
|
|
|
|
hr = ppf->lpVtbl->Save(ppf,
|
|
szLinkPath,
|
|
TRUE);
|
|
if (SUCCEEDED(hr))
|
|
bResult = TRUE;
|
|
|
|
ppf->lpVtbl->Release(ppf);
|
|
}
|
|
|
|
psl->lpVtbl->Release(psl);
|
|
|
|
Ole32.fn.CoUninitialize();
|
|
UnloadDynamicImports(&Ole32);
|
|
|
|
DPRINT("AddItemW() done\n");
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DeleteItemA(LPCSTR lpGroupName, /* Optional */
|
|
BOOL bCommonGroup,
|
|
LPCSTR lpItemName,
|
|
BOOL bDeleteGroup)
|
|
{
|
|
UNICODE_STRING GroupName;
|
|
UNICODE_STRING ItemName;
|
|
BOOL bResult;
|
|
|
|
if (lpGroupName != NULL)
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&GroupName,
|
|
(LPSTR)lpGroupName))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&ItemName,
|
|
(LPSTR)lpItemName))
|
|
{
|
|
if (lpGroupName != NULL)
|
|
{
|
|
RtlFreeUnicodeString(&GroupName);
|
|
}
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
bResult = DeleteItemW((lpGroupName != NULL) ? GroupName.Buffer : NULL,
|
|
bCommonGroup,
|
|
ItemName.Buffer,
|
|
bDeleteGroup);
|
|
|
|
RtlFreeUnicodeString(&ItemName);
|
|
if (lpGroupName != NULL)
|
|
{
|
|
RtlFreeUnicodeString(&GroupName);
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
DeleteItemW(LPCWSTR lpGroupName, /* Optional */
|
|
BOOL bCommonGroup,
|
|
LPCWSTR lpItemName,
|
|
BOOL bDeleteGroup)
|
|
{
|
|
WCHAR szItemPath[MAX_PATH];
|
|
LPWSTR Ptr;
|
|
|
|
DPRINT("DeleteItemW() called\n");
|
|
|
|
if (!GetProgramsPath(bCommonGroup, szItemPath))
|
|
{
|
|
DPRINT1("GetProgramsPath() failed\n");
|
|
return FALSE;
|
|
}
|
|
DPRINT("Programs path: '%S'\n", szItemPath);
|
|
|
|
if (lpGroupName != NULL && *lpGroupName != 0)
|
|
{
|
|
wcscat(szItemPath, L"\\");
|
|
wcscat(szItemPath, lpGroupName);
|
|
}
|
|
|
|
wcscat(szItemPath, L"\\");
|
|
wcscat(szItemPath, lpItemName);
|
|
wcscat(szItemPath, L".lnk");
|
|
DPRINT("Item path: '%S'\n", szItemPath);
|
|
|
|
if (!DeleteFileW(szItemPath))
|
|
return FALSE;
|
|
|
|
/* FIXME: Notify the shell */
|
|
|
|
if (bDeleteGroup)
|
|
{
|
|
Ptr = wcsrchr(szItemPath, L'\\');
|
|
if (Ptr == NULL)
|
|
return TRUE;
|
|
|
|
*Ptr = 0;
|
|
DPRINT("Item path: '%S'\n", szItemPath);
|
|
if (RemoveDirectoryW(szItemPath))
|
|
{
|
|
/* FIXME: Notify the shell */
|
|
}
|
|
}
|
|
|
|
DPRINT("DeleteItemW() done\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* EOF */
|