windows-nt/Source/XPSP1/NT/admin/services/sched/folderui/prshtx.cxx
2020-09-26 16:20:57 +08:00

755 lines
15 KiB
C++

//____________________________________________________________________________
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 1996.
//
// File: psx.cxx
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 2/13/1996 RaviR Created
//
//____________________________________________________________________________
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "dbg.h"
#include "macros.h"
#include "resource.h"
//#include "jobidl.hxx"
#include "util.hxx"
//
// extern
//
extern HINSTANCE g_hInstance;
#define HINST_THISDLL g_hInstance
//
// Local constants
//
TCHAR const FAR c_szNULL[] = TEXT("");
TCHAR const FAR c_szStubWindowClass[] = TEXT("JobPropWnd");
const size_t MAX_FILE_PROP_PAGES = 32;
class CHkey
{
public:
CHkey(void) : _h(NULL) {}
CHkey(HKEY h) : _h(h) {}
virtual ~CHkey() { if (_h != NULL) RegCloseKey(_h); }
operator HKEY() { return _h; }
HKEY * operator &() { return &_h; }
HKEY Attach(HKEY h) { HKEY hTemp = _h; _h = h; return hTemp; }
HKEY Detach(void) { HKEY hTemp = _h; _h = NULL; return hTemp; }
void Close(void) { if (_h) RegCloseKey(_h); _h = NULL; }
protected:
HKEY _h;
};
/////////////////////////////////////////////////////////////////////////////
//
// Display properties
//
class CJFPropertyThreadData
{
public:
static CJFPropertyThreadData * Create(LPDATAOBJECT pdtobj,
LPTSTR pszCaption);
~CJFPropertyThreadData()
{
if (_pdtobj != NULL)
{
_pdtobj->Release();
}
delete _pszCaption;
}
LPDATAOBJECT GetDataObject() { return _pdtobj; }
LPTSTR GetCaption() { return _pszCaption; }
private:
CJFPropertyThreadData() : _pdtobj(NULL), _pszCaption(NULL) {}
LPDATAOBJECT _pdtobj;
LPTSTR _pszCaption;
};
CJFPropertyThreadData *
CJFPropertyThreadData::Create(
LPDATAOBJECT pdtobj,
LPTSTR pszCaption)
{
CJFPropertyThreadData * pData = new CJFPropertyThreadData;
if (pData == NULL)
{
return NULL;
}
pData->_pszCaption = NewDupString(pszCaption);
if (pData->_pszCaption == NULL)
{
delete pData;
return NULL;
}
pData->_pdtobj = pdtobj;
pData->_pdtobj->AddRef();
return pData;
}
DWORD
__stdcall
JFPropertiesThread(
LPVOID pvData)
{
CJFPropertyThreadData *pData = (CJFPropertyThreadData *)pvData;
HRESULT hrOle = OleInitialize(NULL);
__try
{
if (SUCCEEDED(hrOle))
{
JFOpenPropSheet(pData->GetDataObject(), pData->GetCaption());
}
}
__finally
{
delete pData;
if (SUCCEEDED(hrOle))
{
OleUninitialize();
}
ExitThread(0);
}
return 0;
}
//____________________________________________________________________________
//
// Member: CJobsCM::_DisplayJobProperties
//
// Arguments: [hwnd] -- IN
// [pwszJob] -- IN
//
// Returns: HRESULT.
//
// History: 1/11/1996 RaviR Created
//
//____________________________________________________________________________
HRESULT
CJobsCM::_DisplayJobProperties(
HWND hwnd,
CJobID & jid)
{
TRACE_FUNCTION(DisplayJobProperties);
Win4Assert(m_cidl == 1);
HRESULT hr = S_OK;
LPDATAOBJECT pdtobj = NULL;
do
{
hr = JFGetDataObject(hwnd, m_pszFolderPath, m_cidl,
(LPCITEMIDLIST *)m_apidl, (LPVOID *)&pdtobj);
CHECK_HRESULT(hr);
BREAK_ON_FAIL(hr);
CJFPropertyThreadData * pData = NULL;
TCHAR tcName[MAX_PATH];
lstrcpy(tcName, ((PJOBID)m_apidl[0])->GetName());
LPTSTR pszExt = PathFindExtension(tcName);
if (pszExt)
{
*pszExt = TEXT('\0');
}
pData = CJFPropertyThreadData::Create(pdtobj, tcName);
if (pData == NULL)
{
hr = E_OUTOFMEMORY;
CHECK_HRESULT(hr);
break;
}
HANDLE hThread;
DWORD idThread;
hThread = CreateThread(NULL, 0, JFPropertiesThread,
pData, 0, &idThread);
if (hThread)
{
CloseHandle(hThread);
}
else
{
delete pData;
}
} while (0);
if (pdtobj != NULL)
{
pdtobj->Release();
}
return hr;
}
//-----------------------------------------------------------------------------
//
// PSXA
//
// An array of IShellPropSheetExt interface pointers
//
//-----------------------------------------------------------------------------
struct PSXA
{
static PSXA * Alloc(UINT count);
static void Delete(PSXA * pPsxa);
UINT count;
IShellPropSheetExt *intfc[1];
};
PSXA * PSXA::Alloc(UINT count)
{
UINT cb = sizeof(UINT) + sizeof(IShellPropSheetExt *) * count;
PSXA * pPsxa = (PSXA *)new BYTE[cb];
if (pPsxa != NULL)
{
ZeroMemory(pPsxa, cb);
}
return pPsxa;
}
void PSXA::Delete(PSXA * pPsxa)
{
while (pPsxa->count--)
{
if (pPsxa->intfc[pPsxa->count] != NULL)
{
pPsxa->intfc[pPsxa->count]->Release();
}
}
delete [] ((LPBYTE)pPsxa);
}
HRESULT
GetHkeyForJobObject(
HKEY * phkey)
{
//
// Get ProgID for .job files. Get an HKEY for this ProgID.
//
LRESULT lr = ERROR_SUCCESS;
do
{
HKEY hkey = NULL;
lr = RegOpenKeyEx(HKEY_CLASSES_ROOT, TSZ_DOTJOB, 0,
KEY_QUERY_VALUE, &hkey);
if (lr != ERROR_SUCCESS)
{
CHECK_LASTERROR(lr);
break;
}
DWORD dwType = 0;
TCHAR buff[200];
ULONG cb = sizeof(buff);
lr = RegQueryValueEx(hkey, NULL, NULL, &dwType, (LPBYTE)buff, &cb);
RegCloseKey(hkey);
if (lr != ERROR_SUCCESS)
{
CHECK_LASTERROR(lr);
break;
}
hkey = NULL; // reset
lr = RegOpenKeyEx(HKEY_CLASSES_ROOT, buff, 0, KEY_READ, &hkey);
if (lr != ERROR_SUCCESS)
{
CHECK_LASTERROR(lr);
break;
}
*phkey = hkey;
} while (0);
return HRESULT_FROM_WIN32(lr);
}
LPTSTR
I_GetWord(
LPTSTR psz)
{
static TCHAR * s_psz = NULL;
if (psz != NULL)
{
s_psz = psz;
}
psz = s_psz;
// skip the space or comma characters
while (*psz == TEXT(' ') || *psz == TEXT(',')) { ++psz; }
s_psz = psz;
while (*s_psz != TEXT('\0'))
{
if (*s_psz == TEXT(' ') || *s_psz == TEXT(','))
{
*s_psz = TEXT('\0');
++s_psz;
break;
}
++s_psz;
}
return psz;
}
inline
HRESULT
I_CLSIDFromString(
LPTSTR pszClsid,
LPCLSID pclsid)
{
#ifdef UNICODE
return CLSIDFromString(pszClsid, pclsid);
#else
WCHAR wBuff[64];
HRESULT hr = AnsiToUnicode(wBuff, pszClsid, 64);
if (FAILED(hr))
{
return hr;
}
return CLSIDFromString(wBuff, pclsid);
#endif
}
inline
BOOL
I_IsPresent(
CLSID aclsid[],
UINT count)
{
for (UINT i=0; i < count; i++)
{
if (IsEqualCLSID(aclsid[i], aclsid[count]))
{
return TRUE;
}
}
return FALSE;
}
HRESULT
GetPropSheetExtArray(
HKEY hkeyIn,
PSXA ** ppPsxa)
{
*ppPsxa = NULL; // init
//
// From HKEY determine the clsids. Bind to each clsid
// and get the IShellPropSheetExt interface ptrs.
//
HRESULT hr = S_OK;
LRESULT lr = ERROR_SUCCESS;
CHkey hkey;
UINT count = 0;
CLSID aclsid[20];
TCHAR szClsid[64];
ULONG SIZEOF_SZCLSID = sizeof(szClsid);
do
{
TCHAR buff[MAX_PATH * 2];
ULONG SIZEOF_BUFF = sizeof(buff);
ULONG cb = SIZEOF_BUFF;
lr = RegOpenKeyEx(hkeyIn, STRREG_SHEX_PROPSHEET, 0, KEY_READ, &hkey);
BREAK_ON_ERROR(lr);
lr = RegQueryValueEx(hkey, NULL, NULL, NULL, (LPBYTE)buff, &cb);
CHECK_LASTERROR(lr);
if (lr == ERROR_SUCCESS & cb > 0)
{
LPTSTR psz = I_GetWord(buff);
CHkey hkeyTemp = NULL;
while (*psz != TEXT('\0'))
{
hkeyTemp.Close();
lr = RegOpenKeyEx(hkey, psz, 0, KEY_READ, &hkeyTemp);
BREAK_ON_ERROR(lr);
cb = SIZEOF_SZCLSID;
lr = RegQueryValueEx(hkeyTemp, NULL, NULL, NULL,
(LPBYTE)szClsid, &cb);
BREAK_ON_ERROR(lr);
hr = I_CLSIDFromString(szClsid, &aclsid[count]);
BREAK_ON_FAIL(hr);
++count;
psz = I_GetWord(NULL);
}
}
for (int i=0; ; i++)
{
cb = SIZEOF_SZCLSID;
lr = RegEnumKeyEx(hkey, i, szClsid, &cb,
NULL, NULL, NULL, NULL);
BREAK_ON_ERROR(lr);
// Is it a classid?
hr = I_CLSIDFromString(szClsid, &aclsid[count]);
if (FAILED(hr)) // no - see if the value is a classid
{
CHkey hkey3;
lr = RegOpenKeyEx(hkey, szClsid, 0, KEY_READ, &hkey3);
if (lr == ERROR_SUCCESS)
{
cb = SIZEOF_SZCLSID;
lr = RegQueryValueEx(hkey3, NULL, NULL, NULL,
(LPBYTE)szClsid, &cb);
if (lr == ERROR_SUCCESS)
{
hr = I_CLSIDFromString(szClsid, &aclsid[count]);
}
}
}
if (SUCCEEDED(hr))
{
// is it already present ?
if (I_IsPresent(aclsid, count) == FALSE)
{
++count;
}
}
}
} while (0);
if (count <= 0)
{
DEBUG_OUT((DEB_USER1, "No pages to display.\n"));
return E_FAIL;
}
do
{
//
// Now create the IShellPropSheetExt interface ptrs.
//
PSXA * pPsxa = PSXA::Alloc(count);
if (pPsxa == NULL)
{
hr = E_OUTOFMEMORY;
CHECK_HRESULT(hr);
break;
}
for (UINT k=0; k < count; k++)
{
hr = CoCreateInstance(aclsid[k], NULL, CLSCTX_ALL,
IID_IShellPropSheetExt, (void **)&pPsxa->intfc[pPsxa->count]);
CHECK_HRESULT(hr);
if (SUCCEEDED(hr))
{
++pPsxa->count;
}
}
if (pPsxa->count > 0)
{
*ppPsxa = pPsxa;
hr = S_OK;
}
else
{
hr = E_FAIL;
}
} while (0);
return hr;
}
//
// This function is a callback function from property sheet page extensions.
//
BOOL CALLBACK I_AddPropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam)
{
PROPSHEETHEADER * ppsh = (PROPSHEETHEADER *)lParam;
if (ppsh->nPages < MAX_FILE_PROP_PAGES)
{
ppsh->phpage[ppsh->nPages++] = hpage;
return TRUE;
}
return FALSE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage)
{
case WM_CREATE:
break;
case WM_DESTROY:
break;
case WM_NOTIFY:
break;
// case STUBM_SETDATA:
// SetWindowLongPtr(hWnd, 0, wParam);
// break;
//
// case STUBM_GETDATA:
// return GetWindowLongPtr(hWnd, 0);
default:
return DefWindowProc(hWnd, iMessage, wParam, lParam) ;
break;
}
return 0L;
}
HWND I_CreateStubWindow(void)
{
WNDCLASS wndclass;
if (!GetClassInfo(HINST_THISDLL, c_szStubWindowClass, &wndclass))
{
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = HINST_THISDLL;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = c_szStubWindowClass;
if (!RegisterClass(&wndclass))
return NULL;
}
return CreateWindowEx(WS_EX_TOOLWINDOW, c_szStubWindowClass, c_szNULL,
WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
NULL, NULL, HINST_THISDLL, NULL);
}
HRESULT
JFOpenPropSheet(
LPDATAOBJECT pdtobj,
LPTSTR pszCaption)
{
HRESULT hr = S_OK;
CHkey hkey;
PSXA * pPsxa = NULL;
PROPSHEETHEADER psh;
HPROPSHEETPAGE ahpage[MAX_FILE_PROP_PAGES];
do
{
//
// Get HKEY for the .job class object
//
hr = GetHkeyForJobObject(&hkey);
BREAK_ON_FAIL(hr);
//
// Get the IShellPropSheetExt interface ptrs for classes wishing to
// add pages.
//
hr = GetPropSheetExtArray(hkey, &pPsxa);
BREAK_ON_FAIL(hr);
// For each IShellPropSheetExt interface ptr initialize(IShellExtInit)
// and call the AddPages.
psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_PROPTITLE;
psh.hwndParent = I_CreateStubWindow();
psh.hInstance = g_hInstance;
psh.hIcon = NULL;
psh.pszCaption = pszCaption;
//psh.pszCaption = MAKEINTRESOURCE(IDS_JOB_PSH_CAPTION);
psh.nPages = 0; // incremented in callback
psh.nStartPage = 0;
psh.phpage = ahpage;
IShellExtInit * pShExtInit = NULL;
for (UINT n=0; n < pPsxa->count; n++)
{
hr = pPsxa->intfc[n]->QueryInterface(IID_IShellExtInit,
(void **)&pShExtInit);
CHECK_HRESULT(hr);
if (SUCCEEDED(hr))
{
hr = pShExtInit->Initialize(NULL, pdtobj, hkey);
CHECK_HRESULT(hr);
pShExtInit->Release();
if (SUCCEEDED(hr))
{
hr = pPsxa->intfc[n]->AddPages(I_AddPropSheetPage,
(LPARAM)&psh);
CHECK_HRESULT(hr);
}
}
}
PSXA::Delete(pPsxa);
// create a modeless property sheet.
// Open the property sheet, only if we have some pages.
if (psh.nPages > 0)
{
_try
{
hr = E_FAIL;
if (PropertySheet(&psh) >= 0) // IDOK or IDCANCEL (< 0 is error)
{
hr = S_OK;
}
DEBUG_OUT((DEB_USER1, "PropertySheet returned.\n"));
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
hr = E_FAIL;
CHECK_HRESULT(hr);
}
}
} while (0);
if (psh.hwndParent)
{
DestroyWindow(psh.hwndParent);
}
return hr;
}