1
0
mirror of https://github.com/UzixLS/KernelEx.git synced 2025-07-18 23:11:19 +03:00
Files
KernelEx/apilibs/kexbasen/shell32/SHGetFolderLocation.c
2018-11-03 16:19:29 +03:00

308 lines
7.7 KiB
C
Executable File

/*
* Path Functions
*
* Copyright 1998, 1999, 2000 Juergen Schmied
* Copyright 2004 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#ifdef _MSC_VER
#pragma warning(disable:4002)
#define TRACE() ((void)0)
#define TRACE_() ((void)0)
#define WARN() ((void)0)
#else
#define TRACE(...) do {} while(0)
#define TRACE_(x) TRACE
#define WARN(...) do {} while(0)
#endif
#define _WIN32_IE 0x0500
#include <windows.h>
#include <shlguid.h>
#include "auxshlguid.h"
#include "pidl.h"
#include <shlwapi.h>
#include "common.h"
#include "_shell32_apilist.h"
#include "auxdecl.h"
EXTERN_C HRESULT WINAPI SHILCreateFromPathA(LPCSTR path, LPITEMIDLIST *ppidl, DWORD *attributes); /* ORDINAL 28 */
EXTERN_C LPVOID WINAPI SHAlloc(DWORD len); /* ORDINAL 196 */
EXTERN_C void WINAPI SHFree(LPVOID pv); /* ORDINAL 195 */
EXTERN_C LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl); /* ORDINAL 153 */
EXTERN_C LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); /* ORDINAL 25 */
/**************************************************************************
*
* internal functions
*
* ### 1. section creating pidls ###
*
*************************************************************************
*/
LPITEMIDLIST _ILAlloc(PIDLTYPE type, unsigned int size)
{
LPITEMIDLIST pidlOut = NULL;
pidlOut = (LPITEMIDLIST) SHAlloc(size + 5);
if(pidlOut)
{
LPPIDLDATA pData;
LPITEMIDLIST pidlNext;
ZeroMemory(pidlOut, size + 5);
pidlOut->mkid.cb = size + 3;
pData = _ILGetDataPointer(pidlOut);
if (pData)
pData->type = type;
pidlNext = ILGetNext(pidlOut);
if (pidlNext)
pidlNext->mkid.cb = 0x00;
TRACE("-- (pidl=%p, size=%u)\n", pidlOut, size);
}
return pidlOut;
}
LPITEMIDLIST _ILCreateDesktop()
{
LPITEMIDLIST ret;
TRACE("()\n");
ret = (LPITEMIDLIST) SHAlloc(2);
if (ret)
ret->mkid.cb = 0;
return ret;
}
LPITEMIDLIST _ILCreateMyComputer()
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_MyComputer);
}
LPITEMIDLIST _ILCreateMyDocuments()
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_MyDocuments);
}
LPITEMIDLIST _ILCreateIExplore()
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_Internet);
}
LPITEMIDLIST _ILCreateControlPanel()
{
LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL;
TRACE("()\n");
if (parent)
{
LPITEMIDLIST cpl = _ILCreateGuid(PT_SHELLEXT, &CLSID_ControlPanel);
if (cpl)
{
ret = ILCombine(parent, cpl);
SHFree(cpl);
}
SHFree(parent);
}
return ret;
}
LPITEMIDLIST _ILCreatePrinters()
{
LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL;
TRACE("()\n");
if (parent)
{
LPITEMIDLIST printers = _ILCreateGuid(PT_YAGUID, &CLSID_Printers);
if (printers)
{
ret = ILCombine(parent, printers);
SHFree(printers);
}
SHFree(parent);
}
return ret;
}
LPITEMIDLIST _ILCreateNetwork()
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_NetworkPlaces);
}
LPITEMIDLIST _ILCreateBitBucket()
{
TRACE("()\n");
return _ILCreateGuid(PT_GUID, &CLSID_RecycleBin);
}
LPITEMIDLIST _ILCreateGuid(PIDLTYPE type, const IID *guid)
{
LPITEMIDLIST pidlOut;
if (type == PT_SHELLEXT || type == PT_GUID || type == PT_YAGUID)
{
pidlOut = _ILAlloc(type, sizeof(GUIDStruct));
if (pidlOut)
{
LPPIDLDATA pData = _ILGetDataPointer(pidlOut);
memcpy(&(pData->u.guid.guid), guid, sizeof(GUID));
TRACE("-- create GUID-pidl %s\n",
debugstr_guid(&(pData->u.guid.guid)));
}
}
else
{
WARN("%d: invalid type for GUID\n", type);
pidlOut = NULL;
}
return pidlOut;
}
/**************************************************************************
*
* ### 4. getting pointers to parts of pidls ###
*
**************************************************************************
* _ILGetDataPointer()
*/
LPPIDLDATA _ILGetDataPointer(LPCITEMIDLIST pidl)
{
if(pidl && pidl->mkid.cb != 0x00)
return (LPPIDLDATA) &(pidl->mkid.abID);
return NULL;
}
/*************************************************************************
* SHGetFolderLocation [SHELL32.@]
*
* Gets the folder locations from the registry and creates a pidl.
*
* PARAMS
* hwndOwner [I]
* nFolder [I] CSIDL_xxxxx
* hToken [I] token representing user, or NULL for current user, or -1 for
* default user
* dwReserved [I] must be zero
* ppidl [O] PIDL of a special folder
*
* RETURNS
* Success: S_OK
* Failure: Standard OLE-defined error result, S_FALSE or E_INVALIDARG
*
* NOTES
* Creates missing reg keys and directories.
* Mostly forwards to SHGetFolderPathW, but a few values of nFolder return
* virtual folders that are handled here.
*/
/* MAKE_EXPORT SHGetFolderLocation_new=SHGetFolderLocation */
HRESULT WINAPI SHGetFolderLocation_new(
HWND hwndOwner,
int nFolder,
HANDLE hToken,
DWORD dwReserved,
LPVOID *_ppidl)
{
LPITEMIDLIST *ppidl = (LPITEMIDLIST*) _ppidl;
HRESULT hr = E_INVALIDARG;
TRACE("%p 0x%08x %p 0x%08lx %p\n",
hwndOwner, nFolder, hToken, dwReserved, ppidl);
if (!ppidl)
return E_INVALIDARG;
if (dwReserved)
return E_INVALIDARG;
/* The virtual folders' locations are not user-dependent */
*ppidl = NULL;
switch (nFolder)
{
case CSIDL_DESKTOP:
*ppidl = _ILCreateDesktop();
break;
case CSIDL_PERSONAL:
*ppidl = _ILCreateMyDocuments();
break;
case CSIDL_INTERNET:
*ppidl = _ILCreateIExplore();
break;
case CSIDL_CONTROLS:
*ppidl = _ILCreateControlPanel();
break;
case CSIDL_PRINTERS:
*ppidl = _ILCreatePrinters();
break;
case CSIDL_BITBUCKET:
*ppidl = _ILCreateBitBucket();
break;
case CSIDL_DRIVES:
*ppidl = _ILCreateMyComputer();
break;
case CSIDL_NETWORK:
*ppidl = _ILCreateNetwork();
break;
default:
{
char szPath[MAX_PATH];
hr = SHGetFolderPathA_new(hwndOwner, nFolder, hToken,
SHGFP_TYPE_CURRENT, szPath);
if (SUCCEEDED(hr))
{
DWORD attributes=0;
TRACE("Value=%s\n", debugstr_w(szPath));
hr = SHILCreateFromPathA(szPath, ppidl, &attributes);
}
else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
/* unlike SHGetFolderPath, SHGetFolderLocation in shell32
* version 6.0 returns E_FAIL for nonexistent paths
*/
hr = E_FAIL;
}
}
}
if(*ppidl)
hr = NOERROR;
TRACE("-- (new pidl %p)\n",*ppidl);
return hr;
}