Windows2000/private/shell/shell32/unicpp/cmdfile.cpp
2020-09-30 17:12:32 +02:00

409 lines
10 KiB
C++

// this file implements shell command files.
// .scf
// when executed, they run a shell internal command.
// they can have stream storage, or whatnot in them
// file format is *PURPOSELY* text so that folks can create and modify by hand
#include "stdafx.h"
#pragma hdrstop
#define SZDESKBAR TEXT("DeskBar")
LPBYTE GetProfileData(LPCTSTR pszSection, LPCTSTR pszSizeValue, LPCTSTR pszDataValue, LPCTSTR pszFile, UINT *puSize)
{
LPBYTE p = NULL;
if (!pszSizeValue)
pszSizeValue = TEXT("size");
UINT uSize = GetPrivateProfileInt(pszSection, pszSizeValue, 0, pszFile);
if (uSize) {
// use LocalAlloc so that we can strictly pass it to CreateStreamOnHLocal
p = (LPBYTE)LocalAlloc(LPTR, uSize);
if (!GetPrivateProfileStruct(pszSection, pszDataValue, p, uSize, pszFile)) {
LocalFree(p);
p = NULL;
}
}
if (puSize)
*puSize = uSize;
return p;
}
IStream* GetProfileStream(LPCTSTR pszSection, LPCTSTR pszSizeValue, LPCTSTR pszDataValue, LPCTSTR pszFile)
{
UINT uSize;
LPBYTE p = GetProfileData(pszSection, pszSizeValue, pszDataValue, pszFile, &uSize);
IStream* pstm = NULL;
if (p) {
pstm = SHCreateMemStream(p, uSize);
LocalFree(p);
}
return pstm;
}
HWND GetInProcDesktop()
{
HWND hwndDesktop = GetShellWindow(); // This is the "normal" desktop
if (IsDesktopWindow(hwndDesktop))
{
DWORD dwProcID;
GetWindowThreadProcessId(hwndDesktop, &dwProcID);
if (GetCurrentProcessId() == dwProcID) {
return hwndDesktop;
}
}
return NULL;
}
IUnknown* CreateBandFromFile(LPCTSTR pszFile)
{
TCHAR szClass[80];
IUnknown* punk = NULL;
if (!GetPrivateProfileString(SZDESKBAR, TEXT("CLSID"), TEXT(""), szClass, ARRAYSIZE(szClass), pszFile)) {
// if not found, get the stream and do OleLoadFromStream
IStream* pstm = GetProfileStream(SZDESKBAR, NULL, TEXT("Stream"), pszFile);
if (pstm) {
OleLoadFromStream(pstm, IID_IUnknown, (LPVOID*)&punk);
pstm->Release();
}
} else {
CLSID clsid;
if (SHCLSIDFromString(szClass, &clsid))
{
if (SUCCEEDED(CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (LPVOID*)&punk))) {
IStream* pstm = GetProfileStream(SZDESKBAR, NULL, TEXT("Stream"), pszFile);
if (pstm) {
IPersistStream *ppstm;
punk->QueryInterface(IID_IPersistStream, (LPVOID*)&ppstm);
if (ppstm) {
ppstm->Load(pstm);
ppstm->Release();
}
pstm->Release();
}
}
}
}
return punk;
}
void SFC_IECommand(LPCTSTR pszFile)
{
// ANSI!
TCHAR szCommand[40];
if (GetPrivateProfileString(TEXT("IE"), TEXT("Command"), TEXT(""), szCommand, ARRAYSIZE(szCommand), pszFile)) {
if (!lstrcmpi(szCommand, TEXT("Channels"))
&& !SHRestricted2W(REST_NoChannelUI, NULL, 0))
{
Channel_QuickLaunch();
}
}
}
void SFC_BandFile(LPCTSTR pszFile)
{
HWND hwndDesktop = GetInProcDesktop();
if (!hwndDesktop)
return;
LPTSTR psz = StrDup(pszFile);
if (!PostMessage(hwndDesktop, DTM_BANDFILE, 0, (LPARAM)psz))
LocalFree(psz);
}
#if 0
void SFC_DesktopCommand(LPCTSTR pszFile)
{
UINT uID = GetPrivateProfileInt(TEXT("Desktop"), TEXT("Command"), 0, pszFile);
if (uID) {
HWND hwndDesktop = GetInProcDesktop();
PostMessage(hwndDesktop, uID, 0, 0);
}
}
#endif
extern HWND g_hwndTray; // desktop.cpp
void SFC_TrayCommand(LPCTSTR pszFile)
{
// ANSI!
TCHAR szCommand[40];
ASSERT(g_hwndTray);
if (GetPrivateProfileString(TEXT("Taskbar"), TEXT("Command"), TEXT(""), szCommand, ARRAYSIZE(szCommand), pszFile)) {
char szAnsiCommand[40];
SHTCharToAnsi(szCommand, szAnsiCommand, ARRAYSIZE(szAnsiCommand));
LPSTR psz = StrDupA(szAnsiCommand);
if (psz) {
if(!PostMessage(g_hwndTray, TM_PRIVATECOMMAND, 0, (LPARAM)psz))
LocalFree(psz);
}
}
}
enum {
SCFIDM_NOCOMMAND = 0,
SCFIDM_BANDFILE = 1,
SCFIDM_TRAYCOMMAND = 2,
SCFIDM_IE = 3,
};
typedef void (*SFCCOMMAND)(LPCTSTR lpszBuf);
typedef struct _EXECCOMMADNINFO
{
UINT id;
SFCCOMMAND pfn;
} EXECCOMMANDINFO;
EXECCOMMANDINFO const c_sCmdInfo[] =
{
{ SCFIDM_BANDFILE, SFC_BandFile},
{ SCFIDM_TRAYCOMMAND, SFC_TrayCommand},
{ SCFIDM_IE, SFC_IECommand},
};
void ShellExecCommandFile(LPITEMIDLIST pidl)
{
TCHAR szFile[MAX_PATH];
if (SHGetPathFromIDList(pidl, szFile)) {
UINT uID;
uID = GetPrivateProfileInt(TEXT("Shell"), TEXT("Command"), 0, szFile);
if (uID) {
int i;
for ( i = 0; i < ARRAYSIZE(c_sCmdInfo); i++) {
if (uID == c_sCmdInfo[i].id) {
c_sCmdInfo[i].pfn(szFile);
break;
}
}
}
}
}
class CCmdFileIcon : public IExtractIconA, public IExtractIconW, public IPersistFile
{
public:
// *** IUnknown methods ***
STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppvObj);
STDMETHOD_(ULONG,AddRef) () ;
STDMETHOD_(ULONG,Release) ();
// *** IExtractIconA methods ***
STDMETHOD(GetIconLocation)(
UINT uFlags,
LPSTR szIconFile,
UINT cchMax,
int * piIndex,
UINT * pwFlags);
STDMETHOD(Extract)(
LPCSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize) {return S_FALSE;};
// *** IExtractIconW methods ***
STDMETHOD(GetIconLocation)(
UINT uFlags,
LPWSTR szIconFile,
UINT cchMax,
int * piIndex,
UINT * pwFlags);
STDMETHOD(Extract)(
LPCWSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize) {return S_FALSE;};
// IPersist methods
STDMETHODIMP GetClassID(CLSID *pclsid) { *pclsid = CLSID_CmdFileIcon; return S_OK;};
// IPersistFile methods
STDMETHODIMP IsDirty(void) {return S_FALSE;};
STDMETHODIMP Save(LPCOLESTR pcwszFileName, BOOL bRemember) {return S_OK;};
STDMETHODIMP SaveCompleted(LPCOLESTR pcwszFileName){return S_OK;};
STDMETHODIMP Load(LPCOLESTR pcwszFileName, DWORD dwMode);
STDMETHODIMP GetCurFile(LPOLESTR *ppwszFileName);
CCmdFileIcon() { _cRef = 1; DllAddRef(); };
~CCmdFileIcon() { DllRelease(); };
protected:
UINT _cRef;
TCHAR _szFile[MAX_PATH];
};
ULONG CCmdFileIcon::AddRef()
{
_cRef++;
return _cRef;
}
ULONG CCmdFileIcon::Release()
{
ASSERT(_cRef > 0);
_cRef--;
if (_cRef > 0)
return _cRef;
delete this;
return 0;
}
HRESULT CCmdFileIcon::GetIconLocation( UINT uFlags,
LPTSTR szIconFile,
UINT cchMax,
int * piIndex,
UINT * pwFlags)
{
TCHAR szData[MAX_PATH + 80];
if (_szFile[0]) {
*pwFlags = 0;
*piIndex = 0;
szIconFile[0] = 0;
GetPrivateProfileString(TEXT("Shell"), TEXT("IconFile"), TEXT(""), szData, ARRAYSIZE(szData), _szFile);
*piIndex = PathParseIconLocation(szData);
lstrcpyn(szIconFile, szData, cchMax);
return S_OK;
}
return E_FAIL;
}
#ifdef UNICODE
HRESULT CCmdFileIcon::GetIconLocation( UINT uFlags,
LPSTR szIconFile,
UINT cchMax,
int * piIndex,
UINT * pwFlags)
{
WCHAR szAnsiIconPath[MAX_PATH];
HRESULT hres;
if (SUCCEEDED(hres = GetIconLocation(uFlags, szAnsiIconPath, MAX_PATH, piIndex, pwFlags)))
{
SHUnicodeToAnsi(szAnsiIconPath, szIconFile, cchMax);
}
return hres;
}
#else
HRESULT CCmdFileIcon::GetIconLocation( UINT uFlags,
LPWSTR szIconFile,
UINT cchMax,
int * piIndex,
UINT * pwFlags)
{
CHAR szAnsiIconPath[MAX_PATH];
HRESULT hres;
if (SUCCEEDED(hres = GetIconLocation(uFlags, szAnsiIconPath, MAX_PATH, piIndex, pwFlags)))
{
SHAnsiToUnicode(szAnsiIconPath, szIconFile, cchMax);
}
return hres;
}
#endif
// IPersistFile::Load handler for Intshcut
STDMETHODIMP CCmdFileIcon::Load(LPCOLESTR pwszFile, DWORD dwMode)
{
SHUnicodeToTChar(pwszFile, _szFile, ARRAYSIZE(_szFile));
return S_OK;
}
STDMETHODIMP CCmdFileIcon::GetCurFile(LPOLESTR *ppwszFileName)
{
SHTCharToUnicode(_szFile, *ppwszFileName, MAX_PATH);
return S_OK;
}
HRESULT CCmdFileIcon::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_IExtractIconA))
{
*ppvObj = SAFECAST(this, IExtractIconA*);
}
else if (IsEqualIID(riid, IID_IExtractIconW))
{
*ppvObj = SAFECAST(this, IExtractIconW*);
}
else if (IsEqualIID(riid, IID_IPersistFile) ||
IsEqualIID(riid, IID_IPersist))
{
*ppvObj = SAFECAST(this, IPersistFile*);
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
HRESULT CCmdFileIcon_CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppunk)
{
HRESULT hres;
IUnknown* pObj;
pObj = (IExtractIcon*)new CCmdFileIcon();
if (pObj)
{
hres = pObj->QueryInterface(riid, ppunk);
pObj->Release();
}
else
{
*ppunk = NULL;
hres = E_OUTOFMEMORY;
}
return hres;
}