You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2459 lines
61 KiB
2459 lines
61 KiB
//____________________________________________________________________________
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1996.
|
|
//
|
|
// File: sfolder.cxx
|
|
//
|
|
// Contents: Implementation of IShellFolder for Job Folders
|
|
//
|
|
// Classes: CJobFolder::IShellFolder members
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 1/4/1996 RaviR Created
|
|
// 1-23-1997 DavidMun Destroy notify window upon receiving
|
|
// DVM_WINDOWDESTROY
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
#include "..\pch\headers.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "dbg.h"
|
|
#include "macros.h"
|
|
#include "resource.h"
|
|
#include "..\schedui\rc.h"
|
|
#include "jobidl.hxx"
|
|
#include "jobfldr.hxx"
|
|
#include "policy.hxx"
|
|
#include "..\schedui\timeutil.hxx"
|
|
#include "..\schedui\schedui.hxx"
|
|
#include "util.hxx"
|
|
#include "..\inc\defines.hxx"
|
|
#include "..\inc\misc.hxx"
|
|
#include "..\inc\common.hxx"
|
|
#include "..\inc\sch_cls.hxx"
|
|
#include "atacct.h"
|
|
|
|
#define JF_FSNOTIFY (WM_USER + 0xA1)
|
|
#define STUBM_SETDATA (WM_USER + 0xb1)
|
|
#define STUBM_GETDATA (WM_USER + 0xb2)
|
|
|
|
|
|
#define VIEW_ICON_MENU_ID 28713
|
|
#define VIEW_SMALLICON_MENU_ID 28714
|
|
#define VIEW_LIST_MENU_ID 28715
|
|
#define VIEW_DETAILS_MENU_ID 28716
|
|
|
|
//
|
|
// extern
|
|
//
|
|
|
|
extern HINSTANCE g_hInstance;
|
|
extern "C" UINT g_cfJobIDList;
|
|
extern HANDLE g_hActCtx;
|
|
|
|
HRESULT
|
|
JFGetShellDetails(
|
|
HWND hwnd,
|
|
LPVOID* ppvObj);
|
|
|
|
HRESULT
|
|
JFGetFolderContextMenu(
|
|
HWND hwnd,
|
|
CJobFolder * pCJobFolder,
|
|
LPVOID * ppvObj);
|
|
|
|
HRESULT
|
|
JFGetDataObject(
|
|
LPCTSTR pszFolderPath,
|
|
LPCITEMIDLIST pidlFolder,
|
|
UINT cidl,
|
|
LPCITEMIDLIST * apidl,
|
|
BOOL fCut,
|
|
LPVOID * ppvObj);
|
|
|
|
HRESULT
|
|
JFGetItemContextMenu(
|
|
HWND hwnd,
|
|
ITaskScheduler * pScheduler,
|
|
LPCTSTR ptszMachine,
|
|
LPCTSTR pszFolderPath,
|
|
LPCITEMIDLIST pidlFolder,
|
|
UINT cidl,
|
|
LPCITEMIDLIST* apidl,
|
|
LPVOID * ppvOut);
|
|
|
|
HRESULT
|
|
JFGetExtractIcon(
|
|
LPVOID * ppvObj,
|
|
LPCTSTR pszFolderPath,
|
|
LPCITEMIDLIST pidl);
|
|
|
|
HRESULT
|
|
JFGetExtractIconA(
|
|
LPVOID * ppvObj,
|
|
LPCTSTR pszFolderPath,
|
|
LPCITEMIDLIST pidl);
|
|
|
|
HRESULT
|
|
JFGetEnumIDList(
|
|
ULONG uFlags,
|
|
LPCTSTR pszFolderPath,
|
|
IEnumWorkItems * pEnumJobs,
|
|
LPVOID * ppvObj);
|
|
|
|
|
|
HRESULT
|
|
JFCreateNewQueue(
|
|
HWND hwnd);
|
|
|
|
|
|
void
|
|
OnViewLog(
|
|
LPTSTR lpMachineName,
|
|
HWND hwndOwner);
|
|
|
|
|
|
HRESULT
|
|
GetSchSvcState(
|
|
DWORD &dwCurrState);
|
|
|
|
|
|
HRESULT
|
|
StopScheduler(void);
|
|
|
|
|
|
HRESULT
|
|
StartScheduler(void);
|
|
|
|
BOOL
|
|
UserCanChangeService(
|
|
LPCTSTR ptszServer);
|
|
|
|
HRESULT
|
|
PromptForServiceStart(
|
|
HWND hwnd);
|
|
|
|
HRESULT
|
|
PauseScheduler(
|
|
BOOL fPause);
|
|
|
|
VOID
|
|
SecurityErrorDialog(
|
|
HWND hWndOwner,
|
|
HRESULT hr);
|
|
|
|
VOID
|
|
GetDefaultDomainAndUserName(
|
|
LPTSTR ptszDomainAndUserName,
|
|
ULONG cchBuf);
|
|
|
|
//
|
|
// local funcs
|
|
//
|
|
|
|
HWND
|
|
I_CreateNotifyWnd(void);
|
|
|
|
int
|
|
LocaleStrCmp(LPCTSTR ptsz1, LPCTSTR ptsz2);
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::ParseDisplayName
|
|
//____________________________________________________________________________
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::ParseDisplayName(
|
|
HWND hwndOwner,
|
|
LPBC pbcReserved,
|
|
LPOLESTR lpszDisplayName,
|
|
ULONG * pchEaten,
|
|
LPITEMIDLIST * ppidl,
|
|
ULONG * pdwAttributes)
|
|
{
|
|
TRACE(CJobFolder, ParseDisplayName);
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::EnumObjects
|
|
//
|
|
// Arguments: [hwndOwner] -- IN
|
|
// [grfFlags] -- IN
|
|
// [ppenumIDList] -- OUT
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::EnumObjects(
|
|
HWND hwndOwner,
|
|
DWORD grfFlags,
|
|
LPENUMIDLIST* ppenumUnknown)
|
|
{
|
|
DEBUG_OUT((DEB_USER12, "CJobFolder::EnumObjects<%x>\n", this));
|
|
|
|
*ppenumUnknown = NULL;
|
|
|
|
//
|
|
// We dont support folders.
|
|
//
|
|
|
|
if (!(grfFlags & SHCONTF_NONFOLDERS))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Get the IDList enumerator
|
|
//
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_pScheduler == NULL)
|
|
{
|
|
hr = _InitRest();
|
|
|
|
CHECK_HRESULT(hr);
|
|
}
|
|
|
|
IEnumWorkItems * pEnumJobs = NULL;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// m_pScheduler is not actually a COM object
|
|
// it was created via new, and is an instance of CSchedule
|
|
CSchedule* pScheduler;
|
|
pScheduler = (CSchedule*)m_pScheduler;
|
|
|
|
hr = pScheduler->EnumInternal(&pEnumJobs);
|
|
|
|
if ((hr == E_ACCESSDENIED) && (NULL != hwndOwner))
|
|
{
|
|
WCHAR* pMessage;
|
|
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
|
|
E_ACCESSDENIED, 0, (LPWSTR)&pMessage, 0, NULL))
|
|
{
|
|
MessageBox(hwndOwner, pMessage, NULL, MB_OK);
|
|
LocalFree(pMessage);
|
|
}
|
|
}
|
|
|
|
|
|
CHECK_HRESULT(hr);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = JFGetEnumIDList(grfFlags, m_pszFolderPath,
|
|
pEnumJobs, (LPVOID*)ppenumUnknown);
|
|
CHECK_HRESULT(hr);
|
|
|
|
pEnumJobs->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::BindToObject
|
|
//____________________________________________________________________________
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::BindToObject(
|
|
LPCITEMIDLIST pidl,
|
|
LPBC pbcReserved,
|
|
REFIID riid,
|
|
LPVOID* ppvOut)
|
|
{
|
|
TRACE(CJobFolder, BindToObject);
|
|
|
|
// Job folder doesn't contain sub-folders
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::BindToStorage
|
|
//
|
|
// Note: not used in Win95
|
|
//____________________________________________________________________________
|
|
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::BindToStorage(
|
|
LPCITEMIDLIST pidl,
|
|
LPBC pbcReserved,
|
|
REFIID riid,
|
|
LPVOID* ppvObj)
|
|
{
|
|
TRACE(CJobFolder, BindToStorage);
|
|
|
|
*ppvObj = NULL;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::CompareIDs
|
|
//
|
|
// Arguments: [lParam] -- IN
|
|
// [pidl1] -- IN
|
|
// [pidl2] -- IN
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::CompareIDs(
|
|
LPARAM lCol,
|
|
LPCITEMIDLIST pidl1,
|
|
LPCITEMIDLIST pidl2)
|
|
{
|
|
DEBUG_OUT((DEB_USER12, "CJobFolder::CompareIDs<%d>\n", lCol));
|
|
|
|
HRESULT hr = S_OK;
|
|
int iCmp;
|
|
|
|
if (JF_IsValidID(pidl1) == FALSE || JF_IsValidID(pidl2) == FALSE)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
PJOBID pjid1 = (PJOBID)pidl1;
|
|
PJOBID pjid2 = (PJOBID)pidl2;
|
|
|
|
//
|
|
// Ensure that the template object is always first
|
|
//
|
|
|
|
if (pjid1->IsTemplate() && pjid2->IsTemplate())
|
|
{
|
|
return S_OK; // equal
|
|
}
|
|
|
|
if (pjid1->IsTemplate())
|
|
{
|
|
return ResultFromShort(-1);
|
|
}
|
|
|
|
if (pjid2->IsTemplate())
|
|
{
|
|
return ResultFromShort(1);
|
|
}
|
|
|
|
switch (lCol)
|
|
{
|
|
case COLUMN_LASTRUNTIME:
|
|
iCmp = CompareSystemTime(pjid1->GetLastRunTime(),
|
|
pjid2->GetLastRunTime());
|
|
break;
|
|
|
|
case COLUMN_NEXTRUNTIME:
|
|
{
|
|
TCHAR buff1[MAX_PATH];
|
|
TCHAR buff2[MAX_PATH];
|
|
LPTSTR psz1, psz2;
|
|
|
|
psz1 = pjid1->GetNextRunTimeString(buff1, MAX_PATH, TRUE);
|
|
psz2 = pjid2->GetNextRunTimeString(buff2, MAX_PATH, TRUE);
|
|
|
|
if (psz1 != NULL)
|
|
{
|
|
if (psz2 != NULL)
|
|
{
|
|
iCmp = LocaleStrCmp(psz1, psz2);
|
|
}
|
|
else
|
|
{
|
|
iCmp = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (psz2 != NULL)
|
|
{
|
|
iCmp = -1;
|
|
}
|
|
else
|
|
{
|
|
iCmp = CompareSystemTime(pjid1->GetNextRunTime(),
|
|
pjid2->GetNextRunTime());
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case COLUMN_SCHEDULE:
|
|
{
|
|
TCHAR tszTrig1[SCH_XBIGBUF_LEN];
|
|
TCHAR tszTrig2[SCH_XBIGBUF_LEN];
|
|
|
|
if (pjid1->IsJobFlagOn(TASK_FLAG_DISABLED) == TRUE)
|
|
{
|
|
LoadString(g_hInstance, IDS_DISABLED, tszTrig1, SCH_XBIGBUF_LEN);
|
|
}
|
|
else
|
|
{
|
|
hr = GetTriggerStringFromTrigger(&pjid1->GetTrigger(),
|
|
tszTrig1, SCH_XBIGBUF_LEN, NULL);
|
|
BREAK_ON_FAIL(hr);
|
|
}
|
|
|
|
if (pjid2->IsJobFlagOn(TASK_FLAG_DISABLED) == TRUE)
|
|
{
|
|
LoadString(g_hInstance, IDS_DISABLED, tszTrig2, SCH_XBIGBUF_LEN);
|
|
}
|
|
else
|
|
{
|
|
hr = GetTriggerStringFromTrigger(&pjid2->GetTrigger(),
|
|
tszTrig2, SCH_XBIGBUF_LEN, NULL);
|
|
BREAK_ON_FAIL(hr);
|
|
}
|
|
|
|
iCmp = LocaleStrCmp(tszTrig1, tszTrig2);
|
|
|
|
break;
|
|
}
|
|
|
|
case COLUMN_STATUS:
|
|
{
|
|
iCmp = pjid1->_status - pjid2->_status;
|
|
break;
|
|
}
|
|
|
|
case COLUMN_NAME:
|
|
// Fall through
|
|
|
|
default:
|
|
DEBUG_OUT((DEB_USER12, "CompareIDs<%ws, %ws>\n", pjid1->GetName(),
|
|
pjid2->GetName()));
|
|
|
|
iCmp = LocaleStrCmp(pjid1->GetName(), pjid2->GetName());
|
|
|
|
break;
|
|
|
|
case COLUMN_LASTEXITCODE:
|
|
iCmp = pjid1->GetExitCode() - pjid2->GetExitCode();
|
|
break;
|
|
|
|
case COLUMN_CREATOR:
|
|
iCmp = LocaleStrCmp(pjid1->GetCreator(), pjid2->GetCreator());
|
|
break;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = ResultFromShort(iCmp);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: LocaleStrCmp
|
|
//
|
|
// Synopsis: Do a case insensitive string compare that is safe for any
|
|
// locale.
|
|
//
|
|
// Arguments: [ptsz1] - strings to compare
|
|
// [ptsz2]
|
|
//
|
|
// Returns: -1, 0, or 1 just like lstrcmpi
|
|
//
|
|
// History: 10-28-96 DavidMun Created
|
|
//
|
|
// Notes: This is slower than lstrcmpi, but will work when sorting
|
|
// strings even in Japanese.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
int
|
|
LocaleStrCmp(LPCTSTR ptsz1, LPCTSTR ptsz2)
|
|
{
|
|
int iRet;
|
|
|
|
iRet = CompareString(LOCALE_USER_DEFAULT,
|
|
NORM_IGNORECASE |
|
|
NORM_IGNOREKANATYPE |
|
|
NORM_IGNOREWIDTH,
|
|
ptsz1,
|
|
-1,
|
|
ptsz2,
|
|
-1);
|
|
|
|
if (iRet)
|
|
{
|
|
iRet -= 2; // convert to lstrcmpi-style return -1, 0, or 1
|
|
}
|
|
else
|
|
{
|
|
DEBUG_OUT_LASTERROR;
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::CreateViewObject
|
|
//
|
|
// Arguments: [hwndOwner] -- IN
|
|
// [riid] -- IN
|
|
// [ppvOut] -- IN
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::CreateViewObject(
|
|
HWND hwndOwner,
|
|
REFIID riid,
|
|
LPVOID* ppvOut)
|
|
{
|
|
TRACE(CJobFolder, CreateViewObject);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Only update m_hwndOwner the first time.
|
|
// This function gets called each time the view mode gets changed,
|
|
// but subsequent calls after initial window creation seem to have bogus
|
|
// values for hwndOwner. We don't want to clobber our initial good value.
|
|
//
|
|
if (!m_hwndOwner)
|
|
m_hwndOwner = hwndOwner;
|
|
|
|
*ppvOut = NULL;
|
|
|
|
if (m_pszFolderPath == NULL)
|
|
{
|
|
hr = _InitRest();
|
|
|
|
CHECK_HRESULT(hr);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if (IsEqualIID(riid, IID_IShellView))
|
|
{
|
|
CSFV csfv =
|
|
{
|
|
sizeof(CSFV), // cbSize
|
|
(IShellFolder*)this, // pshf
|
|
NULL, // psvOuter
|
|
m_pidlFldr, // pidl to monitor
|
|
0, // events
|
|
s_JobsFVCallBack, // pfnCallback
|
|
FVM_DETAILS
|
|
};
|
|
|
|
IShellView * pShellView;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SHCreateShellFolderViewEx(&csfv, &pShellView);
|
|
|
|
CHECK_HRESULT(hr);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_pShellView = pShellView;
|
|
// WARNING: Do not AddRef m_pShellView this will cause
|
|
// a cyclic addref. Use DVM_RELEASE in callback to know
|
|
// whem m_pShellView is destroyed.
|
|
}
|
|
|
|
*ppvOut = (LPVOID)m_pShellView;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IShellDetails))
|
|
{
|
|
hr = JFGetShellDetails(hwndOwner, ppvOut);
|
|
}
|
|
else if (IsEqualIID(riid, IID_IContextMenu))
|
|
{
|
|
hr = JFGetFolderContextMenu(hwndOwner, this, ppvOut);
|
|
}
|
|
else if (IsEqualIID(riid, IID_IDropTarget))
|
|
{
|
|
hr = this->QueryInterface(IID_IDropTarget, ppvOut);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
CHECK_HRESULT(hr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::GetAttributesOf
|
|
//
|
|
// Arguments: [cidl] -- IN
|
|
// [apidl] -- IN
|
|
// [rgfInOut] -- IN
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
// 5-09-1997 DavidMun handle template object
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::GetAttributesOf(
|
|
UINT cidl,
|
|
LPCITEMIDLIST* apidl,
|
|
ULONG* rgfInOut)
|
|
{
|
|
// TRACE(CJobFolder, GetAttributesOf);
|
|
|
|
//
|
|
// Three cases:
|
|
//
|
|
// a. list contains only non-template object(s)
|
|
// b. list contains only a template object
|
|
// c. list contains template object plus non-template object(s)
|
|
//
|
|
// For cases b and c, no operations are allowed, since the
|
|
// template object is not a real object.
|
|
//
|
|
|
|
ULONG rgfMask;
|
|
|
|
if (ContainsTemplateObject(cidl, apidl))
|
|
{
|
|
rgfMask = 0;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Policy - creation, deletion are regulated
|
|
//
|
|
|
|
rgfMask = 0;
|
|
|
|
//
|
|
// If no DRAG and DROP restriction, then it ok to copy.
|
|
// read it once, for efficiency's sake.
|
|
//
|
|
|
|
BOOL fDragDropRestricted = RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP);
|
|
BOOL fDeleteRestricted = RegReadPolicyKey(TS_KEYPOLICY_DENY_DELETE);
|
|
|
|
if (! fDragDropRestricted)
|
|
{
|
|
rgfMask |= SFGAO_CANCOPY;
|
|
}
|
|
|
|
if ((! fDeleteRestricted) && (! fDragDropRestricted))
|
|
{
|
|
// If allowed deletion, then move or delete is okay
|
|
rgfMask |= SFGAO_CANMOVE;
|
|
|
|
if (! RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK))
|
|
{
|
|
//
|
|
// If allowed creation, as well, then rename is okay
|
|
// Note we consider a RENAME both a create and a delete
|
|
//
|
|
|
|
rgfMask |= SFGAO_CANRENAME;
|
|
}
|
|
}
|
|
|
|
if (! fDeleteRestricted)
|
|
{
|
|
rgfMask |= SFGAO_CANDELETE;
|
|
}
|
|
|
|
if ((cidl == 1) && (! RegReadPolicyKey(TS_KEYPOLICY_DENY_PROPERTIES)))
|
|
{
|
|
// no multi-select property sheets
|
|
rgfMask |= SFGAO_HASPROPSHEET|SFGAO_FILESYSTEM ;
|
|
}
|
|
}
|
|
|
|
*rgfInOut &= rgfMask;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::GetUIObjectOf
|
|
//
|
|
// Arguments: [hwndOwner] -- IN
|
|
// [cidl] -- IN
|
|
// [apidl] -- IN
|
|
// [riid] -- IN
|
|
// [prgfInOut] -- IN
|
|
// [ppvOut] -- IN
|
|
//
|
|
// Returns: STDMETHODIMP
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::GetUIObjectOf(
|
|
HWND hwndOwner,
|
|
UINT cidl,
|
|
LPCITEMIDLIST* apidl,
|
|
REFIID riid,
|
|
UINT* prgfInOut,
|
|
LPVOID* ppvOut)
|
|
{
|
|
TRACE(CJobFolder, GetUIObjectOf);
|
|
|
|
if( NULL == apidl )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
PJOBID pjid = (PJOBID)apidl[0];
|
|
|
|
if (cidl < 1)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (JF_IsValidID(apidl[0]) == FALSE)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
*ppvOut = NULL;
|
|
|
|
if (cidl == 1 && IsEqualIID(riid, IID_IExtractIcon))
|
|
{
|
|
hr = JFGetExtractIcon(ppvOut, m_pszFolderPath, apidl[0]);
|
|
}
|
|
else if (cidl == 1 && IsEqualIID(riid, IID_IExtractIconA))
|
|
{
|
|
hr = JFGetExtractIconA(ppvOut, m_pszFolderPath, apidl[0]);
|
|
}
|
|
else if (IsEqualIID(riid, IID_IContextMenu))
|
|
{
|
|
if (m_pszFolderPath == NULL)
|
|
{
|
|
hr = _InitRest();
|
|
CHECK_HRESULT(hr);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = JFGetItemContextMenu(hwndOwner,
|
|
m_pScheduler,
|
|
m_pszMachine,
|
|
m_pszFolderPath,
|
|
m_pidlFldr,
|
|
cidl,
|
|
apidl,
|
|
ppvOut);
|
|
}
|
|
else if (cidl > 0 && IsEqualIID(riid, IID_IDataObject))
|
|
{
|
|
DEBUG_OUT((DEB_USER1, "[GetUIObjectOf] IDataObject \n"));
|
|
|
|
BOOL fCut = (GetKeyState(VK_CONTROL) >= 0);
|
|
|
|
//
|
|
// Policy - if DRAGDROP or DELETE and we are here,
|
|
// we must be doing a cut or copy op and cannot allow it
|
|
//
|
|
|
|
if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP) ||
|
|
(fCut && RegReadPolicyKey(TS_KEYPOLICY_DENY_DELETE)))
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
DEBUG_OUT((DEB_USER12, "fCut<%d>\n", fCut));
|
|
|
|
hr = JFGetDataObject(m_pszFolderPath,
|
|
m_pidlFldr,
|
|
cidl,
|
|
apidl,
|
|
fCut,
|
|
ppvOut);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::GetDisplayNameOf
|
|
//
|
|
// Arguments: [pidl] -- IN
|
|
// [uFlags] -- IN
|
|
// [lpName] -- IN
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::GetDisplayNameOf(
|
|
LPCITEMIDLIST pidl,
|
|
DWORD uFlags,
|
|
LPSTRRET lpName)
|
|
{
|
|
TRACE(CJobFolder, GetDisplayNameOf);
|
|
DEBUG_OUT((DEB_USER12, "CJobFolder::GetDisplayNameOf<uFlags = %d>\n", uFlags));
|
|
|
|
if (JF_IsValidID(pidl) == FALSE)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
PJOBID pjid_unaligned = (PJOBID)pidl;
|
|
DWORD SizeForAlignment = pjid_unaligned->_cb + sizeof(ULONG_PTR);
|
|
CJobID * pjid = (CJobID *)LocalAlloc(LPTR,SizeForAlignment);
|
|
if (NULL == pjid)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
};
|
|
class CFreeMe { void * _p; public: CFreeMe(void * p):_p(p){}; ~CFreeMe(){ LocalFree(_p);};} FreeMe(pjid);
|
|
|
|
memcpy(pjid, pjid_unaligned, pjid_unaligned->_cb);
|
|
|
|
LPTSTR ptszToReturn;
|
|
TCHAR tszFullPath[MAX_PATH + 1];
|
|
|
|
//
|
|
// If the display name is to be used for parsing, return the full path to
|
|
// the file. This is used by rshx32.dll when we request that it add the
|
|
// security page for a file.
|
|
//
|
|
|
|
if (uFlags & SHGDN_FORPARSING)
|
|
{
|
|
//
|
|
// If we don't have the folder path, complete the initialization to
|
|
// get it.
|
|
//
|
|
|
|
if (m_pszFolderPath == NULL)
|
|
{
|
|
HRESULT hr = _InitRest();
|
|
CHECK_HRESULT(hr);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
StringCchPrintf(tszFullPath,
|
|
MAX_PATH + 1,
|
|
TEXT("%s\\%s.") TSZ_JOB,
|
|
m_pszFolderPath,
|
|
pjid->GetName());
|
|
|
|
|
|
ptszToReturn = tszFullPath;
|
|
DEBUG_OUT((DEB_TRACE,
|
|
"CJobFolder::GetDisplayNameOf: Returning path '%S'\n",
|
|
ptszToReturn));
|
|
}
|
|
else
|
|
{
|
|
ptszToReturn = pjid->GetName();
|
|
}
|
|
|
|
UINT uiByteLen = (lstrlen(ptszToReturn) + 1) * sizeof(TCHAR);
|
|
|
|
lpName->uType = STRRET_WSTR;
|
|
|
|
lpName->pOleStr = (LPWSTR) SHAlloc(uiByteLen);
|
|
|
|
if (NULL == lpName->pOleStr)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
CopyMemory(lpName->pOleStr, ptszToReturn, uiByteLen);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::SetNameOf
|
|
//
|
|
// Arguments: [hwndOwner] -- IN
|
|
// [pidl] -- IN
|
|
// [lpszName] -- IN
|
|
// [uFlags] -- IN
|
|
// [ppidlOut] -- IN
|
|
//
|
|
// Returns: STDMETHODIMP
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::SetNameOf(
|
|
HWND hwndOwner,
|
|
LPCITEMIDLIST pidl,
|
|
LPCOLESTR lpszName,
|
|
DWORD uFlags,
|
|
LPITEMIDLIST* ppidlOut)
|
|
{
|
|
TRACE(CJobFolder, SetNameOf);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (JF_IsValidID(pidl) == FALSE)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
PJOBID pjidOld = (PJOBID)pidl;
|
|
|
|
DEBUG_ASSERT(!pjidOld->IsTemplate());
|
|
|
|
if (ppidlOut != NULL)
|
|
{
|
|
*ppidlOut = NULL;
|
|
}
|
|
|
|
CJobID jidNew;
|
|
|
|
jidNew.Rename(*pjidOld, lpszName);
|
|
|
|
//
|
|
// Change the file name
|
|
//
|
|
|
|
TCHAR szOldFile[MAX_PATH + 2];
|
|
TCHAR szNewFile[MAX_PATH + 2];
|
|
BOOL fRet;
|
|
|
|
StringCchCopy(szOldFile, MAX_PATH + 2, m_pszFolderPath);
|
|
StringCchCat(szOldFile, MAX_PATH + 2, TEXT("\\"));
|
|
StringCchCat(szOldFile, MAX_PATH + 2, pjidOld->GetPath());
|
|
StringCchCat(szOldFile, MAX_PATH + 2, TSZ_DOTJOB);
|
|
|
|
StringCchCopy(szNewFile, MAX_PATH + 2, m_pszFolderPath);
|
|
StringCchCat(szNewFile, MAX_PATH + 2, TEXT("\\"));
|
|
StringCchCat(szNewFile, MAX_PATH + 2, jidNew.GetName());
|
|
StringCchCat(szNewFile, MAX_PATH + 2, TSZ_DOTJOB);
|
|
|
|
DEBUG_OUT((DEB_USER1, "Rename %ws to %ws\n", szOldFile, szNewFile));
|
|
|
|
SHFILEOPSTRUCT fo;
|
|
|
|
fo.hwnd = m_hwndOwner;
|
|
fo.wFunc = FO_RENAME;
|
|
fo.pFrom = szOldFile;
|
|
fo.pTo = szNewFile;
|
|
fo.fFlags = FOF_ALLOWUNDO;
|
|
fo.fAnyOperationsAborted = FALSE;
|
|
fo.hNameMappings = NULL;
|
|
fo.lpszProgressTitle = NULL;
|
|
|
|
// Make sure we have double trailing NULL!
|
|
*(szOldFile + lstrlen(szOldFile) + 1) = TEXT('\0');
|
|
*(szNewFile + lstrlen(szNewFile) + 1) = TEXT('\0');
|
|
|
|
if ((SHFileOperation(&fo) !=0) || fo.fAnyOperationsAborted == TRUE)
|
|
{
|
|
hr = E_FAIL;
|
|
CHECK_HRESULT(hr);
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// IShellFolder2
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::GetDefaultSearchGUID(GUID *pguid)
|
|
{
|
|
return E_NOTIMPL;
|
|
};
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::EnumSearches(IEnumExtraSearch **ppenum)
|
|
{
|
|
return E_NOTIMPL;
|
|
};
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
|
|
{
|
|
if (NULL == pSort || NULL == pDisplay)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
*pSort = COLUMN_NEXTRUNTIME;
|
|
*pDisplay = COLUMN_NAME;
|
|
return S_OK;
|
|
};
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::GetDefaultColumnState( UINT iColumn, SHCOLSTATEF *pcsFlags)
|
|
{
|
|
if (NULL == pcsFlags)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
if (iColumn >= COLUMN_COUNT)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
switch(iColumn)
|
|
{
|
|
case COLUMN_NAME:
|
|
case COLUMN_SCHEDULE:
|
|
*pcsFlags = SHCOLSTATE_ONBYDEFAULT |SHCOLSTATE_TYPE_STR;
|
|
break;
|
|
case COLUMN_NEXTRUNTIME:
|
|
case COLUMN_LASTRUNTIME:
|
|
*pcsFlags = SHCOLSTATE_ONBYDEFAULT |SHCOLSTATE_TYPE_DATE;
|
|
break;
|
|
case COLUMN_STATUS:
|
|
case COLUMN_COUNT:
|
|
*pcsFlags = SHCOLSTATE_ONBYDEFAULT |SHCOLSTATE_TYPE_INT;
|
|
break;
|
|
default:
|
|
*pcsFlags = SHCOLSTATE_ONBYDEFAULT;
|
|
};
|
|
|
|
return S_OK;
|
|
};
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::GetDetailsEx( LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
|
|
{
|
|
return E_NOTIMPL;
|
|
};
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::GetDetailsOf( LPCITEMIDLIST pidl,UINT iColumn,SHELLDETAILS *psd)
|
|
{
|
|
return E_NOTIMPL;
|
|
};
|
|
|
|
STDMETHODIMP
|
|
CJobFolder::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
|
|
{
|
|
return E_NOTIMPL;
|
|
};
|
|
|
|
|
|
|
|
#if DBG==1
|
|
void JFDbgOutCallbackMsg(UINT uMsg);
|
|
#endif // DBG==1
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::s_JobsFVCallBack, static
|
|
//
|
|
// Arguments: [psvOuter] -- IN
|
|
// [psf] -- IN
|
|
// [hwndOwner] -- IN
|
|
// [uMsg] -- IN
|
|
// [wParam] -- IN
|
|
// [lParam] -- IN
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
HRESULT CALLBACK
|
|
CJobFolder::s_JobsFVCallBack(
|
|
LPSHELLVIEW psvOuter,
|
|
LPSHELLFOLDER psf,
|
|
HWND hwndOwner,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
CJobFolder *pCJobFolder = (CJobFolder *)psf;
|
|
|
|
return pCJobFolder->_JobsFVCallBack(psvOuter, psf, hwndOwner,
|
|
uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: EnableAtAccountControls
|
|
//
|
|
// Synopsis: Enable or disable the account and password controls in the
|
|
// at account dialog.
|
|
//
|
|
// Arguments: [hDlg] - handle to dialog
|
|
// [fEnable] - TRUE = enable, FALSE = disable
|
|
//
|
|
// History: 09-19-96 DavidMun Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
EnableAtAccountControls(HWND hDlg, BOOL fEnable)
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDD_AT_CUSTOM_ACCT_NAME), fEnable);
|
|
EnableWindow(GetDlgItem(hDlg, IDD_AT_PASSWORD), fEnable);
|
|
EnableWindow(GetDlgItem(hDlg, IDD_AT_CONFIRM_PASSWORD), fEnable);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: InitAtAccountDlg
|
|
//
|
|
// Synopsis: Initialize the controls in the at account dialog
|
|
//
|
|
// Arguments: [hDlg] - handle to dialog
|
|
//
|
|
// History: 09-19-96 DavidMun Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
InitAtAccountDlg(HWND hDlg)
|
|
{
|
|
HRESULT hr;
|
|
WCHAR wszAccount[MAX_USERNAME + 1];
|
|
DWORD cchAccount = MAX_USERNAME + 1;
|
|
|
|
//
|
|
// Limit the length of account and password edit controls, and init the
|
|
// password controls to stars just like the task account dialog does.
|
|
//
|
|
|
|
SendDlgItemMessage(hDlg,
|
|
IDD_AT_CUSTOM_ACCT_NAME,
|
|
EM_LIMITTEXT,
|
|
MAX_USERNAME,
|
|
0);
|
|
|
|
SendDlgItemMessage(hDlg,
|
|
IDD_AT_PASSWORD,
|
|
EM_LIMITTEXT,
|
|
MAX_PASSWORD,
|
|
0);
|
|
|
|
SendDlgItemMessage(hDlg,
|
|
IDD_AT_CONFIRM_PASSWORD,
|
|
EM_LIMITTEXT,
|
|
MAX_PASSWORD,
|
|
0);
|
|
|
|
//
|
|
// Ask the service for the current at account information. Menu item for
|
|
// this dialog should be disabled if service isn't running, so this should
|
|
// succeed. If this fails, we can't expect the Set api to work, so
|
|
// complain and bail.
|
|
//
|
|
|
|
hr = GetNetScheduleAccountInformation(NULL, cchAccount, wszAccount);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (hr == S_FALSE)
|
|
{
|
|
// running as local system
|
|
CheckDlgButton(hDlg, IDD_AT_USE_SYSTEM, BST_CHECKED);
|
|
EnableAtAccountControls(hDlg, FALSE);
|
|
}
|
|
else
|
|
{
|
|
CheckDlgButton(hDlg, IDD_AT_USE_CUSTOM, BST_CHECKED);
|
|
SetDlgItemText(hDlg, IDD_AT_CUSTOM_ACCT_NAME, wszAccount);
|
|
EnableAtAccountControls(hDlg, TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SchedUIMessageDialog(hDlg,
|
|
IERR_GETATACCOUNT,
|
|
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
|
|
NULL);
|
|
EndDialog(hDlg, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HandleAtAccountChange
|
|
//
|
|
// Synopsis: Make the At account reflect the current settings in the
|
|
// dialog, and end the dialog if successful.
|
|
//
|
|
// Arguments: [hDlg] - handle to dialog
|
|
//
|
|
// History: 09-19-96 DavidMun Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
HandleAtAccountChange(HWND hDlg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR wszAccountName[MAX_USERNAME + 1] = TEXT("");
|
|
WCHAR wszPassword[MAX_PASSWORD + 1] = TEXT("");
|
|
WCHAR wszConfirmedPassword[MAX_PASSWORD + 1] = TEXT("");
|
|
|
|
do
|
|
{
|
|
//
|
|
// See if user just wants at jobs to run as localsystem
|
|
//
|
|
|
|
if (IsDlgButtonChecked(hDlg, IDD_AT_USE_SYSTEM) == BST_CHECKED)
|
|
{
|
|
hr = SetNetScheduleAccountInformation(NULL, NULL, wszPassword);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
SecurityErrorDialog(hDlg, hr);
|
|
}
|
|
else
|
|
{
|
|
EndDialog(hDlg, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// No, we have to validate account and password controls. Get the
|
|
// account name and fail if it's empty.
|
|
//
|
|
|
|
GetDlgItemText(hDlg,
|
|
IDD_AT_CUSTOM_ACCT_NAME,
|
|
wszAccountName,
|
|
MAX_USERNAME + 1);
|
|
|
|
if (wszAccountName[0] == L'\0')
|
|
{
|
|
SchedUIErrorDialog(hDlg, IERR_ACCOUNTNAME, (LPTSTR)NULL);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the passwords and fail if they haven't been changed, or if
|
|
// they don't match eachother.
|
|
//
|
|
|
|
GetDlgItemText(hDlg,
|
|
IDD_AT_PASSWORD,
|
|
wszPassword,
|
|
MAX_PASSWORD + 1);
|
|
|
|
GetDlgItemText(hDlg,
|
|
IDD_AT_CONFIRM_PASSWORD,
|
|
wszConfirmedPassword,
|
|
MAX_PASSWORD + 1);
|
|
|
|
if (lstrcmp(wszPassword, wszConfirmedPassword) != 0)
|
|
{
|
|
SchedUIErrorDialog(hDlg, IERR_PASSWORD, (LPTSTR)NULL);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Account name and passwords valid (as far as we can tell). Make
|
|
// the change to the account.
|
|
//
|
|
|
|
hr = SetNetScheduleAccountInformation(NULL, // local machine
|
|
wszAccountName,
|
|
wszPassword);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
SecurityErrorDialog(hDlg, hr);
|
|
}
|
|
else
|
|
{
|
|
EndDialog(hDlg, 0);
|
|
}
|
|
} while (0);
|
|
|
|
SecureZeroMemory(wszPassword, sizeof wszPassword);
|
|
SecureZeroMemory(wszConfirmedPassword, sizeof wszPassword);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SetAtAccountDlgProc
|
|
//
|
|
// Synopsis: Allow the user to specify which account to run AT jobs under
|
|
//
|
|
// Arguments: standard dialog proc
|
|
//
|
|
// Returns: standard dialog proc
|
|
//
|
|
// History: 09-19-96 DavidMun Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
INT_PTR APIENTRY
|
|
SetAtAccountDlgProc(
|
|
HWND hDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
BOOL fHandled = TRUE;
|
|
|
|
//
|
|
// Note: the DWLP_USER long is used as a dirty flag. If the user hits OK
|
|
// without having modified the edit controls or hit the radio buttons,
|
|
// then we'll just treat it as a Cancel if the dirty flag is FALSE.
|
|
//
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
InitAtAccountDlg(hDlg);
|
|
SetWindowLongPtr(hDlg, DWLP_USER, FALSE);
|
|
break; // return TRUE so windows will set focus
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDD_AT_USE_SYSTEM:
|
|
EnableAtAccountControls(hDlg, FALSE);
|
|
SetWindowLongPtr(hDlg, DWLP_USER, TRUE);
|
|
break;
|
|
|
|
case IDD_AT_USE_CUSTOM:
|
|
{
|
|
WCHAR wszUserName[MAX_USERNAME + 1];
|
|
DWORD cchUserName = MAX_USERNAME + 1;
|
|
|
|
SetWindowLongPtr(hDlg, DWLP_USER, TRUE);
|
|
|
|
//
|
|
// If there's nothing in the user account field, make it default
|
|
// to the logged-on user.
|
|
//
|
|
|
|
if (!GetDlgItemText(hDlg,
|
|
IDD_AT_CUSTOM_ACCT_NAME,
|
|
wszUserName,
|
|
cchUserName))
|
|
{
|
|
GetDefaultDomainAndUserName(wszUserName, cchUserName);
|
|
SetDlgItemText(hDlg, IDD_AT_CUSTOM_ACCT_NAME, wszUserName);
|
|
}
|
|
|
|
EnableAtAccountControls(hDlg, TRUE);
|
|
break;
|
|
}
|
|
|
|
case IDD_AT_CUSTOM_ACCT_NAME:
|
|
case IDD_AT_PASSWORD:
|
|
case IDD_AT_CONFIRM_PASSWORD:
|
|
if (EN_CHANGE == HIWORD(wParam))
|
|
{
|
|
SetWindowLongPtr(hDlg, DWLP_USER, TRUE);
|
|
}
|
|
else
|
|
{
|
|
fHandled = FALSE;
|
|
}
|
|
break;
|
|
|
|
case IDOK:
|
|
if (GetWindowLongPtr(hDlg, DWLP_USER))
|
|
{
|
|
//
|
|
// Do NOT clear the dirty flag here--if HandleAtAccountChange
|
|
// is successful, the dialog will end, but if not we need to
|
|
// retain the dirty state.
|
|
//
|
|
|
|
CWaitCursor WaitCursor;
|
|
HandleAtAccountChange(hDlg);
|
|
break;
|
|
}
|
|
// else FALL THROUGH
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, wParam);
|
|
break;
|
|
|
|
default:
|
|
fHandled = FALSE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fHandled = FALSE;
|
|
break;
|
|
}
|
|
return fHandled;
|
|
}
|
|
|
|
|
|
//____________________________________________________________________________
|
|
//
|
|
// Member: CJobFolder::_JobsFVCallBack
|
|
//
|
|
// Arguments: [psvOuter] -- IN
|
|
// [psf] -- IN
|
|
// [hwndOwner] -- IN
|
|
// [uMsg] -- IN
|
|
// [wParam] -- IN
|
|
// [lParam] -- IN
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// History: 1/5/1996 RaviR Created
|
|
//
|
|
//____________________________________________________________________________
|
|
|
|
HRESULT CALLBACK
|
|
CJobFolder::_JobsFVCallBack(
|
|
LPSHELLVIEW psvOuter,
|
|
LPSHELLFOLDER psf,
|
|
HWND hwndOwner,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DEBUG_OUT((DEB_USER12, "_JobsFVCallBack<uMsg=%d>\n", uMsg));
|
|
|
|
HRESULT hr = S_OK;
|
|
LRESULT lr = ERROR_SUCCESS;
|
|
|
|
switch(uMsg)
|
|
{
|
|
case DVM_GETCCHMAX:
|
|
{
|
|
UINT * pcchMax = (UINT *)lParam;
|
|
|
|
// <folder path> + '\' + cchMax + '.job' + null <= MAX_PATH
|
|
|
|
*pcchMax = MAX_PATH - (lstrlen(m_pszFolderPath) + 6);
|
|
|
|
break;
|
|
}
|
|
case DVM_DEFITEMCOUNT:
|
|
//
|
|
// If DefView times out enumerating items, let it know we probably only
|
|
// have about 20 items
|
|
//
|
|
|
|
*(int *)lParam = 20;
|
|
break;
|
|
|
|
case DVM_MERGEMENU:
|
|
{
|
|
m_qcm = *((LPQCMINFO)lParam);
|
|
|
|
UtMergeMenu(g_hInstance, POPUP_ADVANCED, POPUP_JOBS_MAIN_POPUPMERGE,
|
|
(LPQCMINFO)lParam);
|
|
break;
|
|
}
|
|
case DVM_INITMENUPOPUP:
|
|
{
|
|
UINT idCmdFirst = LOWORD(wParam);
|
|
UINT nIndex = HIWORD(wParam);
|
|
HMENU hmenu = (HMENU)lParam;
|
|
UINT idCmd = GetMenuItemID(hmenu, 0) - idCmdFirst;
|
|
|
|
if (idCmd == FSIDM_STOP_SCHED)
|
|
{
|
|
if (!UserCanChangeService(m_pszMachine))
|
|
{
|
|
//
|
|
// The job folder is on a remote machine, or we're on NT
|
|
// and the user is not an administrator. Disable stop,
|
|
// pause, and at account options and get out.
|
|
//
|
|
|
|
EnableMenuItem(hmenu, FSIDM_STOP_SCHED+idCmdFirst,
|
|
MF_DISABLED | MF_GRAYED);
|
|
|
|
EnableMenuItem(hmenu, FSIDM_PAUSE_SCHED+idCmdFirst,
|
|
MF_DISABLED | MF_GRAYED);
|
|
|
|
EnableMenuItem(hmenu, FSIDM_NOTIFY_MISSED+idCmdFirst,
|
|
MF_DISABLED | MF_GRAYED);
|
|
EnableMenuItem(hmenu, FSIDM_AT_ACCOUNT+idCmdFirst,
|
|
MF_DISABLED | MF_GRAYED);
|
|
break;
|
|
}
|
|
|
|
DWORD dwState;
|
|
|
|
hr = GetSchSvcState(dwState);
|
|
|
|
DEBUG_OUT((DEB_USER1, "Service state = %d\n", dwState));
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
dwState = SERVICE_STOPPED;
|
|
}
|
|
|
|
UINT uiStartID = IDS_MI_STOP;
|
|
UINT uiPauseID = IDS_MI_PAUSE;
|
|
UINT uiPauseEnable = MFS_ENABLED;
|
|
#define CCH_MENU_TEXT 80
|
|
TCHAR tszStart[CCH_MENU_TEXT];
|
|
TCHAR tszPause[CCH_MENU_TEXT];
|
|
|
|
if (dwState == SERVICE_STOPPED ||
|
|
dwState == SERVICE_STOP_PENDING)
|
|
{
|
|
uiStartID = IDS_MI_START;
|
|
uiPauseEnable = MFS_DISABLED;
|
|
}
|
|
else if (dwState == SERVICE_PAUSED ||
|
|
dwState == SERVICE_PAUSE_PENDING)
|
|
{
|
|
uiPauseID = IDS_MI_CONTINUE;
|
|
}
|
|
|
|
if (dwState == SERVICE_START_PENDING)
|
|
{
|
|
uiPauseEnable = MFS_DISABLED;
|
|
}
|
|
|
|
MENUITEMINFO mii = {0};
|
|
mii.cbSize = sizeof(MENUITEMINFO);
|
|
|
|
mii.fMask = MIIM_TYPE;
|
|
|
|
LoadString(g_hInstance, uiStartID, tszStart, CCH_MENU_TEXT);
|
|
mii.dwTypeData = tszStart;
|
|
|
|
SetMenuItemInfo(hmenu, FSIDM_STOP_SCHED+idCmdFirst, FALSE,
|
|
&mii);
|
|
|
|
mii.fMask = MIIM_TYPE | MIIM_STATE;
|
|
|
|
LoadString(g_hInstance, uiPauseID, tszPause, CCH_MENU_TEXT);
|
|
mii.dwTypeData = tszPause;
|
|
mii.fState = uiPauseEnable;
|
|
|
|
SetMenuItemInfo(hmenu, FSIDM_PAUSE_SCHED+idCmdFirst, FALSE,
|
|
&mii);
|
|
|
|
CheckMenuItem(hmenu,
|
|
FSIDM_NOTIFY_MISSED+idCmdFirst,
|
|
g_fNotifyMiss ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
EnableMenuItem(hmenu,
|
|
FSIDM_AT_ACCOUNT+idCmdFirst,
|
|
MFS_ENABLED == uiPauseEnable ?
|
|
MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case DVM_INVOKECOMMAND:
|
|
{
|
|
HMENU &hmenu = m_qcm.hmenu;
|
|
UINT id = (UINT)wParam + m_qcm.idCmdFirst;
|
|
DWORD dwState;
|
|
|
|
hr = GetSchSvcState(dwState);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
dwState = SERVICE_STOPPED;
|
|
}
|
|
|
|
switch (wParam)
|
|
{
|
|
case FSIDM_SORTBYNAME:
|
|
ShellFolderView_ReArrange(hwndOwner, COLUMN_NAME);
|
|
break;
|
|
|
|
case FSIDM_SORTBYSCHEDULE:
|
|
ShellFolderView_ReArrange(hwndOwner, COLUMN_SCHEDULE);
|
|
break;
|
|
|
|
case FSIDM_SORTBYNEXTRUNTIME:
|
|
ShellFolderView_ReArrange(hwndOwner, COLUMN_NEXTRUNTIME);
|
|
break;
|
|
|
|
case FSIDM_SORTBYLASTRUNTIME:
|
|
ShellFolderView_ReArrange(hwndOwner, COLUMN_LASTRUNTIME);
|
|
break;
|
|
|
|
case FSIDM_SORTBYSTATUS:
|
|
ShellFolderView_ReArrange(hwndOwner, COLUMN_STATUS);
|
|
break;
|
|
|
|
case FSIDM_SORTBYLASTEXITCODE:
|
|
ShellFolderView_ReArrange(hwndOwner, COLUMN_LASTEXITCODE);
|
|
break;
|
|
|
|
case FSIDM_SORTBYCREATOR:
|
|
ShellFolderView_ReArrange(hwndOwner, COLUMN_CREATOR);
|
|
break;
|
|
|
|
case FSIDM_NEWJOB:
|
|
if (UserCanChangeService(m_pszMachine))
|
|
{
|
|
PromptForServiceStart(hwndOwner);
|
|
}
|
|
hr = CreateAJobForApp(NULL);
|
|
break;
|
|
|
|
case FSIDM_STOP_SCHED:
|
|
if (dwState == SERVICE_STOPPED ||
|
|
dwState == SERVICE_STOP_PENDING)
|
|
{
|
|
hr = StartScheduler();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
SchedUIErrorDialog(hwndOwner, IERR_STARTSVC, (LPTSTR) NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = StopScheduler();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
SchedUIErrorDialog(hwndOwner, IERR_STOPSVC, (LPTSTR) NULL);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case FSIDM_PAUSE_SCHED:
|
|
hr = PauseScheduler(dwState != SERVICE_PAUSED &&
|
|
dwState != SERVICE_PAUSE_PENDING);
|
|
break;
|
|
|
|
case FSIDM_AT_ACCOUNT:
|
|
{
|
|
ULONG_PTR lpCookie = NULL;
|
|
if (ActivateActCtx(g_hActCtx, &lpCookie))
|
|
{
|
|
DialogBox(g_hInstance,
|
|
MAKEINTRESOURCE(IDD_AT_ACCOUNT_DLG),
|
|
hwndOwner,
|
|
SetAtAccountDlgProc);
|
|
|
|
DeactivateActCtx(0, lpCookie);
|
|
}
|
|
else
|
|
{
|
|
DialogBox(g_hInstance,
|
|
MAKEINTRESOURCE(IDD_AT_ACCOUNT_DLG),
|
|
hwndOwner,
|
|
SetAtAccountDlgProc);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FSIDM_NOTIFY_MISSED:
|
|
{
|
|
LONG lErr;
|
|
HKEY hSchedKey = NULL;
|
|
|
|
lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
SCH_AGENT_KEY,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&hSchedKey);
|
|
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
DEBUG_OUT((DEB_ERROR, "RegOpenKeyEx of Scheduler key %uL\n", lErr));
|
|
break;
|
|
}
|
|
|
|
// Toggle the global var state
|
|
|
|
g_fNotifyMiss = !g_fNotifyMiss;
|
|
|
|
// Persist the change in the registry
|
|
|
|
ULONG cbData = sizeof(g_fNotifyMiss);
|
|
|
|
lErr = RegSetValueEx(hSchedKey,
|
|
SCH_NOTIFYMISS_VALUE,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &g_fNotifyMiss,
|
|
cbData);
|
|
RegCloseKey(hSchedKey);
|
|
|
|
// If the change couldn't be persisted, undo it.
|
|
|
|
if (lErr != ERROR_SUCCESS)
|
|
{
|
|
DEBUG_OUT((DEB_ERROR, "RegSetValueEx of notify miss %uL\n", lErr));
|
|
g_fNotifyMiss = !g_fNotifyMiss;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FSIDM_VIEW_LOG:
|
|
OnViewLog(m_pszMachine, hwndOwner);
|
|
break;
|
|
|
|
default:
|
|
DEBUG_OUT((DEB_ERROR, "Unknown DVM_INVOKECOMMAND<%u>\n",wParam));
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case DVM_GETTOOLTIPTEXT:
|
|
case DVM_GETHELPTEXT:
|
|
{
|
|
UINT idCmd = (UINT)LOWORD(wParam);
|
|
UINT cchMax = (UINT)HIWORD(wParam);
|
|
UINT uiToggle = 0;
|
|
|
|
LPSTR pszText = (LPSTR)lParam;
|
|
|
|
if (idCmd == FSIDM_STOP_SCHED || idCmd == FSIDM_PAUSE_SCHED)
|
|
{
|
|
DWORD dwState;
|
|
|
|
hr = GetSchSvcState(dwState);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
dwState = SERVICE_STOPPED;
|
|
}
|
|
|
|
if ((dwState == SERVICE_STOPPED ||
|
|
dwState == SERVICE_STOP_PENDING) &&
|
|
idCmd == FSIDM_STOP_SCHED)
|
|
{
|
|
uiToggle = MH_TEXT_TOGGLE;
|
|
}
|
|
else
|
|
{
|
|
if ((dwState == SERVICE_PAUSED ||
|
|
dwState == SERVICE_PAUSE_PENDING) &&
|
|
idCmd == FSIDM_PAUSE_SCHED)
|
|
{
|
|
uiToggle = MH_TEXT_TOGGLE;
|
|
}
|
|
}
|
|
}
|
|
|
|
LoadString(g_hInstance, idCmd + IDS_MH_FSIDM_FIRST + uiToggle,
|
|
(LPTSTR)pszText, cchMax);
|
|
|
|
break;
|
|
}
|
|
|
|
case DVM_DIDDRAGDROP:
|
|
{
|
|
DEBUG_OUT((DEB_USER12, "DVM_DIDDRAGDROP\n"));
|
|
|
|
// DWORD dwEffect = wParam;
|
|
// IDataObject * pdtobj = (IDataObject *)lParam;
|
|
//
|
|
// if (!(dwEffect & DROPEFFECT_MOVE))
|
|
// {
|
|
// DEBUG_OUT((DEB_USER1, "DVM_DIDDRAGDROP<Copy>\n"));
|
|
// }
|
|
// else
|
|
// {
|
|
// DEBUG_OUT((DEB_USER1, "DVM_DIDDRAGDROP<Move>\n"));
|
|
// }
|
|
|
|
break;
|
|
}
|
|
case DVM_GETWORKINGDIR:
|
|
{
|
|
UINT uMax = (UINT)wParam;
|
|
LPTSTR pszDir = (LPTSTR)lParam;
|
|
|
|
StringCchCopy(pszDir, uMax, m_pszFolderPath);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// DVM_INSERTITEM and DVM_DELETEITEM are not processed because the
|
|
// directory change notifications already provide this information.
|
|
//
|
|
|
|
// case DVM_INSERTITEM:
|
|
// {
|
|
// PJOBID pjid = (PJOBID)wParam;
|
|
// if (JF_IsValidID((LPCITEMIDLIST)pjid) == TRUE)
|
|
// {
|
|
// DEBUG_OUT((DEB_USER1, "DVM_INSERTITEM <%ws>\n", pjid->GetName()));
|
|
// }
|
|
// break;
|
|
// }
|
|
// case DVM_DELETEITEM:
|
|
// {
|
|
// PDVSELCHANGEINFO psci = (PDVSELCHANGEINFO)lParam;
|
|
//
|
|
// PJOBID pjid = (PJOBID)psci->lParamItem;
|
|
//
|
|
// if (pjid == NULL)
|
|
// {
|
|
// DEBUG_OUT((DEB_USER1, "DVM_DELETEITEM delete all items.\n"));
|
|
// }
|
|
// else if (JF_IsValidID((LPCITEMIDLIST)pjid) == TRUE)
|
|
// {
|
|
// DEBUG_OUT((DEB_USER1, "DVM_DELETEITEM <%ws>\n", pjid->GetName()));
|
|
// }
|
|
// break;
|
|
// }
|
|
case DVM_RELEASE:
|
|
{
|
|
DEBUG_OUT((DEB_USER1, "\tDVM_RELEASE\n"));
|
|
m_pShellView = NULL;
|
|
break;
|
|
}
|
|
case DVM_WINDOWCREATED:
|
|
{
|
|
//
|
|
// If we're opening on the local machine, make sure the sa.dat
|
|
// file is up to date.
|
|
//
|
|
|
|
if (!m_pszMachine)
|
|
{
|
|
CheckSaDat(m_pszFolderPath);
|
|
}
|
|
|
|
// Save current listview mode
|
|
|
|
m_ulListViewModeOnEntry = _GetChildListViewMode(hwndOwner);
|
|
|
|
// Register change notifications for the pidl of the Tasks dir
|
|
|
|
DEBUG_ASSERT(!m_hwndNotify);
|
|
m_hwndNotify = I_CreateNotifyWnd();
|
|
|
|
if (m_hwndNotify == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
SendMessage(m_hwndNotify, STUBM_SETDATA, (WPARAM)this, 0);
|
|
|
|
if (m_pszFolderPath == NULL)
|
|
{
|
|
hr = _InitRest();
|
|
|
|
CHECK_HRESULT(hr);
|
|
BREAK_ON_FAIL(hr);
|
|
}
|
|
|
|
LPITEMIDLIST pidl;
|
|
hr = SHILCreateFromPath(m_pszFolderPath, &pidl, NULL);
|
|
|
|
CHECK_HRESULT(hr);
|
|
BREAK_ON_FAIL(hr);
|
|
|
|
SHChangeNotifyEntry fsne;
|
|
fsne.pidl = pidl;
|
|
fsne.fRecursive = FALSE;
|
|
|
|
int fSources = SHCNRF_ShellLevel | SHCNRF_InterruptLevel;
|
|
//| SHCNRF_NewDelivery;
|
|
|
|
LONG fEvents = SHCNE_DISKEVENTS | SHCNE_RENAMEITEM | SHCNE_CREATE |
|
|
SHCNE_UPDATEITEM | SHCNE_ATTRIBUTES | SHCNE_DELETE;
|
|
|
|
CDll::LockServer(TRUE);
|
|
m_uRegister = SHChangeNotifyRegister(m_hwndNotify, fSources, fEvents,
|
|
JF_FSNOTIFY, 1, &fsne);
|
|
|
|
if (!m_uRegister)
|
|
{
|
|
CDll::LockServer(FALSE);
|
|
DEBUG_OUT_LASTERROR;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case DVM_WINDOWDESTROY:
|
|
{
|
|
//
|
|
// Restore the listview mode that we found on entry, unless the
|
|
// user has changed away from report mode.
|
|
//
|
|
|
|
if (m_ulListViewModeOnEntry != INVALID_LISTVIEW_STYLE &&
|
|
_GetChildListViewMode(hwndOwner) == LVS_REPORT)
|
|
{
|
|
_SetViewMode(hwndOwner, m_ulListViewModeOnEntry);
|
|
}
|
|
|
|
if (m_uRegister)
|
|
{
|
|
SHChangeNotifyDeregister(m_uRegister);
|
|
CDll::LockServer(FALSE);
|
|
m_uRegister = 0;
|
|
}
|
|
|
|
if (m_hwndNotify)
|
|
{
|
|
BOOL fOk = DestroyWindow(m_hwndNotify);
|
|
|
|
m_hwndNotify = NULL;
|
|
|
|
if (!fOk)
|
|
{
|
|
DEBUG_OUT_LASTERROR;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case SFVM_GETHELPTOPIC:
|
|
{
|
|
SFVM_HELPTOPIC_DATA * phtd = (SFVM_HELPTOPIC_DATA*)lParam;
|
|
StringCchCopy(phtd->wszHelpFile, MAX_PATH, L"mstask.chm");
|
|
break;
|
|
}
|
|
|
|
default:
|
|
hr = E_FAIL;
|
|
|
|
#if DBG==1
|
|
JFDbgOutCallbackMsg(uMsg);
|
|
#endif // DBG==1
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CJobFolder::_SetViewMode
|
|
//
|
|
// Synopsis: Select the listview mode specified by [ulListViewStyle].
|
|
//
|
|
// Arguments: [hwndOwner] - explorer window handle
|
|
// [ulListViewStyle] - LVS_* in LVS_TYPEMASK.
|
|
//
|
|
// History: 07-25-1997 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void
|
|
CJobFolder::_SetViewMode(
|
|
HWND hwndOwner,
|
|
ULONG ulListViewStyle)
|
|
{
|
|
switch (ulListViewStyle)
|
|
{
|
|
case LVS_ICON:
|
|
PostMessage(hwndOwner, WM_COMMAND, VIEW_ICON_MENU_ID, 0);
|
|
break;
|
|
|
|
case LVS_REPORT:
|
|
PostMessage(hwndOwner, WM_COMMAND, VIEW_DETAILS_MENU_ID, 0);
|
|
break;
|
|
|
|
case LVS_SMALLICON:
|
|
PostMessage(hwndOwner, WM_COMMAND, VIEW_SMALLICON_MENU_ID, 0);
|
|
break;
|
|
|
|
case LVS_LIST:
|
|
PostMessage(hwndOwner, WM_COMMAND, VIEW_LIST_MENU_ID, 0);
|
|
break;
|
|
|
|
default:
|
|
DEBUG_OUT((DEB_ERROR,
|
|
"CJobFolder::_SetViewMode: invalid view mode 0x%x\n",
|
|
ulListViewStyle));
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: EnumChildWindowCallback
|
|
//
|
|
// Synopsis: Fill hwnd pointed to by [lParam] with [hwnd] if [hwnd] has
|
|
// class WC_LISTVIEW.
|
|
//
|
|
//
|
|
// Arguments: [hwnd] - window to check
|
|
// [lParam] - pointer to HWND
|
|
//
|
|
// Returns: TRUE - continue enumeration
|
|
// FALSE - [hwnd] is listview, *(HWND*)[lParam] = [hwnd], stop
|
|
// enumerating
|
|
//
|
|
// Modifies: *(HWND*)[lParam]
|
|
//
|
|
// History: 07-25-1997 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL CALLBACK
|
|
EnumChildWindowCallback(
|
|
HWND hwnd,
|
|
LPARAM lParam)
|
|
{
|
|
TCHAR tszClassName[80];
|
|
|
|
GetClassName(hwnd, tszClassName, ARRAYLEN(tszClassName));
|
|
|
|
if (!lstrcmpi(tszClassName, WC_LISTVIEW))
|
|
{
|
|
*(HWND *)lParam = hwnd;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CJobFolder::_GetChildListViewMode
|
|
//
|
|
// Synopsis: Return the LVS_* value representing the mode of the first
|
|
// child listview control found for [hwndOwner].
|
|
//
|
|
// Arguments: [hwndOwner] -
|
|
//
|
|
// Returns: LVS_ICON, LVS_SMALLICON, LVS_REPORT, LVS_LIST, or
|
|
// INVALID_LISTVIEW_STYLE.
|
|
//
|
|
// History: 07-25-1997 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
ULONG
|
|
CJobFolder::_GetChildListViewMode(
|
|
HWND hwndOwner)
|
|
{
|
|
HWND hwnd = NULL;
|
|
|
|
EnumChildWindows(hwndOwner,
|
|
EnumChildWindowCallback,
|
|
(LPARAM)&hwnd);
|
|
|
|
if (!hwnd)
|
|
{
|
|
DEBUG_OUT((DEB_ERROR,
|
|
"_GetChildListViewMode: can't find child listview\n"));
|
|
return INVALID_LISTVIEW_STYLE;
|
|
}
|
|
|
|
LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
|
|
|
|
return lStyle & LVS_TYPEMASK;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
CJobFolder::_ObjectAlreadyPresent(
|
|
LPTSTR pszObj)
|
|
{
|
|
BOOL fPresent = FALSE;
|
|
|
|
PJOBID pjid;
|
|
LPTSTR pszName = PathFindFileName(pszObj);
|
|
LPTSTR pszExt = PathFindExtension(pszName);
|
|
TCHAR tcSave;
|
|
|
|
if (pszExt)
|
|
{
|
|
tcSave = *pszExt;
|
|
*pszExt = TEXT('\0');
|
|
}
|
|
|
|
int cObjs = (int) ShellFolderView_GetObjectCount(m_hwndOwner);
|
|
|
|
for (int i=0; i < cObjs; i++)
|
|
{
|
|
pjid = (PJOBID)ShellFolderView_GetObject(m_hwndOwner, i);
|
|
|
|
if (lstrcmpi(pjid->GetName(), pszName) == 0)
|
|
{
|
|
fPresent = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pszExt)
|
|
{
|
|
*pszExt = tcSave;
|
|
}
|
|
|
|
return fPresent;
|
|
}
|
|
|
|
LRESULT
|
|
CJobFolder::HandleFsNotify(
|
|
LONG lNotification,
|
|
LPCITEMIDLIST* ppidl)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CJobID jid;
|
|
LRESULT lr;
|
|
TCHAR from[MAX_PATH];
|
|
TCHAR to[MAX_PATH];
|
|
|
|
SHGetPathFromIDList(ppidl[0], from);
|
|
DEBUG_OUT((DEB_USER1, "First pidl<%ws>\n", from));
|
|
|
|
switch (lNotification)
|
|
{
|
|
case SHCNE_RENAMEITEM:
|
|
{
|
|
DEBUG_OUT((DEB_USER1, "SHCNE_RENAMEITEM\n"));
|
|
|
|
LPTSTR psFrom = PathFindFileName(from) - 1;
|
|
*psFrom = TEXT('\0');
|
|
|
|
SHGetPathFromIDList(ppidl[1], to);
|
|
DEBUG_OUT((DEB_USER1, "Second pidl<%ws>\n", to));
|
|
LPTSTR psTo = PathFindFileName(to) - 1;
|
|
*psTo = TEXT('\0');
|
|
|
|
BOOL fFromJF = (lstrcmpi(m_pszFolderPath, from) == 0);
|
|
BOOL fToJF = (lstrcmpi(m_pszFolderPath, to) == 0);
|
|
|
|
*psFrom = TEXT('\\');
|
|
*psTo = TEXT('\\');
|
|
|
|
if (fFromJF == FALSE)
|
|
{
|
|
if (fToJF == FALSE)
|
|
{
|
|
break; // Nothing to do with job folder
|
|
}
|
|
|
|
//
|
|
// ADD object
|
|
//
|
|
|
|
// First check if this object doesn't already exist in the UI
|
|
|
|
if (_ObjectAlreadyPresent(to) == FALSE)
|
|
{
|
|
hr = jid.Load(NULL, to);
|
|
|
|
CHECK_HRESULT(hr);
|
|
BREAK_ON_FAIL(hr);
|
|
|
|
_AddObject(&jid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fToJF == TRUE)
|
|
{
|
|
// Rename
|
|
|
|
hr = jid.Load(NULL, to);
|
|
|
|
CHECK_HRESULT(hr);
|
|
BREAK_ON_FAIL(hr);
|
|
|
|
CJobID jidOld;
|
|
|
|
jidOld.LoadDummy(PathFindFileName(from));
|
|
|
|
hr = _UpdateObject(&jidOld, &jid);
|
|
}
|
|
else
|
|
{
|
|
// Delete
|
|
|
|
// Need to create a dummy jobid
|
|
|
|
jid.LoadDummy(PathFindFileName(from));
|
|
|
|
_RemoveObject(&jid);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case SHCNE_CREATE:
|
|
{
|
|
DEBUG_OUT((DEB_USER1, "SHCNE_CREATE\n"));
|
|
|
|
if (_ObjectAlreadyPresent(from) == FALSE)
|
|
{
|
|
//
|
|
// Not present, so add it.
|
|
//
|
|
|
|
hr = jid.Load(NULL, from);
|
|
|
|
if (hr == S_FALSE)
|
|
{
|
|
//
|
|
// Task is hidden. Don't display it.
|
|
//
|
|
break;
|
|
}
|
|
|
|
CHECK_HRESULT(hr);
|
|
BREAK_ON_FAIL(hr);
|
|
|
|
hr = _AddObject(&jid);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case SHCNE_DELETE:
|
|
DEBUG_OUT((DEB_USER1, "SHCNE_DELETE\n"));
|
|
|
|
jid.LoadDummy(from);
|
|
|
|
_RemoveObject(&jid);
|
|
|
|
break;
|
|
|
|
case SHCNE_UPDATEDIR:
|
|
DEBUG_OUT((DEB_USER1, "SHCNE_UPDATEDIR\n"));
|
|
|
|
this->OnUpdateDir();
|
|
|
|
break;
|
|
|
|
case SHCNE_UPDATEITEM:
|
|
DEBUG_OUT((DEB_USER1, "SHCNE_UPDATEITEM\n"));
|
|
|
|
hr = jid.Load(NULL, from);
|
|
|
|
if (hr == S_FALSE)
|
|
{
|
|
//
|
|
// Task is hidden. Don't display it. Always remove from the ID list
|
|
// to take care of the case where this notification was due to the
|
|
// task being hidden.
|
|
//
|
|
_RemoveObject(&jid);
|
|
break;
|
|
}
|
|
|
|
CHECK_HRESULT(hr);
|
|
BREAK_ON_FAIL(hr);
|
|
|
|
hr = _UpdateObject(&jid, &jid);
|
|
|
|
break;
|
|
|
|
default:
|
|
DEBUG_OUT((DEB_USER1, "JF_FSNOTIFY unprocessed <0x%x>\n", lNotification));
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
|
|
|
|
LRESULT
|
|
CALLBACK
|
|
NotifyWndProc(
|
|
HWND hWnd,
|
|
UINT iMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DEBUG_OUT((DEB_USER12, "NWP<0x%x>\n", iMessage));
|
|
|
|
switch (iMessage)
|
|
{
|
|
case STUBM_SETDATA:
|
|
SetWindowLongPtr(hWnd, 0, wParam);
|
|
return TRUE;
|
|
|
|
case STUBM_GETDATA:
|
|
return GetWindowLongPtr(hWnd, 0);
|
|
|
|
case JF_FSNOTIFY:
|
|
{
|
|
CJobFolder * pjf = (CJobFolder*)GetWindowLongPtr(hWnd, 0);
|
|
|
|
if (pjf == NULL)
|
|
{
|
|
DEBUG_OUT((DEB_ERROR, "NotifyWndProc: NULL CJobFolder pointer\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
pjf->HandleFsNotify((LONG)lParam, (LPCITEMIDLIST*)wParam);
|
|
|
|
return TRUE;
|
|
}
|
|
default:
|
|
return DefWindowProc(hWnd, iMessage, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
TCHAR const c_szNotifyWindowClass[] = TEXT("JF Notify Window Class");
|
|
TCHAR const c_szNULL[] = TEXT("");
|
|
|
|
HWND
|
|
I_CreateNotifyWnd(void)
|
|
{
|
|
WNDCLASS wndclass;
|
|
|
|
if (!GetClassInfo(g_hInstance, c_szNotifyWindowClass, &wndclass))
|
|
{
|
|
wndclass.style = 0;
|
|
wndclass.lpfnWndProc = NotifyWndProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = sizeof(PVOID) * 2;
|
|
wndclass.hInstance = g_hInstance;
|
|
wndclass.hIcon = NULL;
|
|
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
|
wndclass.lpszMenuName = NULL;
|
|
wndclass.lpszClassName = c_szNotifyWindowClass;
|
|
|
|
if (!RegisterClass(&wndclass))
|
|
return NULL;
|
|
}
|
|
|
|
return CreateWindowEx(WS_EX_TOOLWINDOW, c_szNotifyWindowClass, c_szNULL,
|
|
WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
|
|
NULL, NULL, g_hInstance, NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if DBG==1
|
|
void
|
|
JFDbgOutCallbackMsg(
|
|
UINT uMsg)
|
|
{
|
|
#define PROCESS_MSG(M) \
|
|
case M: DEBUG_OUT((DEB_USER12, "UNPROCESSED msg<%s, %d>\n", #M, M)); break;
|
|
|
|
#define DONT_PROCESS_MSG(M) \
|
|
case M: break;
|
|
|
|
switch (uMsg)
|
|
{
|
|
DONT_PROCESS_MSG(DVM_GETHELPTEXT)
|
|
DONT_PROCESS_MSG(DVM_GETTOOLTIPTEXT)
|
|
DONT_PROCESS_MSG(DVM_GETBUTTONINFO)
|
|
DONT_PROCESS_MSG(DVM_GETBUTTONS)
|
|
DONT_PROCESS_MSG(DVM_INITMENUPOPUP)
|
|
|
|
DONT_PROCESS_MSG(DVM_SELCHANGE)
|
|
PROCESS_MSG(DVM_DRAWITEM)
|
|
|
|
DONT_PROCESS_MSG(DVM_MEASUREITEM)
|
|
DONT_PROCESS_MSG(DVM_EXITMENULOOP)
|
|
|
|
PROCESS_MSG(DVM_RELEASE)
|
|
|
|
DONT_PROCESS_MSG(DVM_GETCCHMAX)
|
|
|
|
PROCESS_MSG(DVM_FSNOTIFY)
|
|
|
|
DONT_PROCESS_MSG(DVM_WINDOWCREATED)
|
|
DONT_PROCESS_MSG(DVM_WINDOWDESTROY)
|
|
|
|
PROCESS_MSG(DVM_REFRESH)
|
|
|
|
DONT_PROCESS_MSG(DVM_SETFOCUS)
|
|
DONT_PROCESS_MSG(DVM_KILLFOCUS)
|
|
|
|
PROCESS_MSG(DVM_QUERYCOPYHOOK)
|
|
PROCESS_MSG(DVM_NOTIFYCOPYHOOK)
|
|
|
|
DONT_PROCESS_MSG(DVM_GETDETAILSOF)
|
|
DONT_PROCESS_MSG(DVM_COLUMNCLICK)
|
|
|
|
PROCESS_MSG(DVM_QUERYFSNOTIFY)
|
|
PROCESS_MSG(DVM_DEFITEMCOUNT)
|
|
PROCESS_MSG(DVM_DEFVIEWMODE)
|
|
PROCESS_MSG(DVM_UNMERGEMENU)
|
|
PROCESS_MSG(DVM_INSERTITEM)
|
|
PROCESS_MSG(DVM_DELETEITEM)
|
|
|
|
DONT_PROCESS_MSG(DVM_UPDATESTATUSBAR)
|
|
DONT_PROCESS_MSG(DVM_BACKGROUNDENUM)
|
|
|
|
PROCESS_MSG(DVM_GETWORKINGDIR)
|
|
|
|
DONT_PROCESS_MSG(DVM_GETCOLSAVESTREAM)
|
|
DONT_PROCESS_MSG(DVM_SELECTALL)
|
|
|
|
PROCESS_MSG(DVM_DIDDRAGDROP)
|
|
PROCESS_MSG(DVM_FOLDERISPARENT)
|
|
|
|
default:
|
|
DEBUG_OUT((DEB_USER12, "UNKNOWN message <%d> !!!!\n", uMsg));
|
|
}
|
|
}
|
|
#endif // DBG==1
|