|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 1995.
//
// File: jobfldr.cxx
//
// Contents: Implementation of COM object CJobFolder
//
// Classes: CJobFolder
//
// History: 1/4/1996 RaviR Created
// 1-23-1997 DavidMun Add m_hwndNotify
//
//----------------------------------------------------------------------------
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "dbg.h"
#include "macros.h"
#include "..\inc\resource.h"
#include "resource.h"
#include "sch_cls.hxx" // sched\inc
#include "job_cls.hxx" // sched\inc
#include "misc.hxx" // sched\inc
#include "policy.hxx" // sched\inc
#include "jobidl.hxx"
#include "jobfldr.hxx"
#include "common.hxx"
#include "guids.h"
#include "util.hxx"
#include "avl.hxx"
//#undef DEB_TRACE
//#define DEB_TRACE DEB_USER1
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
BOOL UserCanChangeService( LPCTSTR ptszServer);
HRESULT PromptForServiceStart( HWND hwnd);
BOOL IsMsNetwork( LPTSTR ptszMachine );
//____________________________________________________________________________
//
// Member: CJobFolder::~CJobFolder, Destructor
//____________________________________________________________________________
CJobFolder::~CJobFolder() { TRACE(CJobFolder, ~CJobFolder);
if (m_uRegister) { DEBUG_OUT((DEB_ERROR, "CJobFolder::~CJobFolder: m_uRegister = %uL but should be 0\n", m_uRegister)); SHChangeNotifyDeregister(m_uRegister); m_uRegister = 0; CDll::LockServer(FALSE); }
if (m_hwndNotify) { DEBUG_OUT((DEB_ERROR, "CJobFolder::~CJobFolder: m_hwndNotify = 0x%x but should be NULL\n", m_hwndNotify));
BOOL fOk = DestroyWindow(m_hwndNotify);
if (!fOk) { DEBUG_OUT_LASTERROR; } }
delete m_pszMachine;
if (m_pUpdateDirData) { GlobalFree(m_pUpdateDirData); }
if (m_pidlFldr) { ILFree(m_pidlFldr); }
// No need to Release m_pShellView since we never addrefed it.
// See CreateViewObject in sfolder.cxx for more info.
if (m_pScheduler != NULL) { DEBUG_OUT((DEB_USER1, "m_pScheduler->Release\n")); m_pScheduler->Release(); }
OleUninitialize(); }
HRESULT CJobFolder::_AddObject( PJOBID pjid, LPITEMIDLIST *ppidl) { HRESULT hr = S_OK; INT_PTR iRet = -1;
LPITEMIDLIST pidl = ILClone((LPCITEMIDLIST)pjid);
if (pidl == NULL) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); return hr; }
#if (DBG == 1)
((PJOBID) pidl)->Validate(); #endif // (DBG == 1)
iRet = ShellFolderView_AddObject(m_hwndOwner, pidl);
if (iRet < 0) { ILFree(pidl); pidl = NULL;
hr = E_FAIL; CHECK_HRESULT(hr); }
if (ppidl) { *ppidl = pidl; }
return hr; }
//+--------------------------------------------------------------------------
//
// Member: CJobFolder::_UpdateObject
//
// Synopsis: Notify the shell defview that the object with pidl [pjidOld]
// has been updated and now should look like pidl [pjidNew].
//
// Arguments: [pjidOld] - pidl of object as it appears in defview
// [pjidNew] - pidl of object as it should now appear
// [ppidl] - filled with pidl of updated object
//
// Returns: HRESULT
//
// Modifies: *[ppidl]
//
// History: 7-07-1999 davidmun Commented
//
// Notes: Do not free returned pidl in *[ppidl].
//
//---------------------------------------------------------------------------
HRESULT CJobFolder::_UpdateObject( PJOBID pjidOld, PJOBID pjidNew, LPITEMIDLIST *ppidl) { TRACE(CJobFolder, _UpdateObject);
HRESULT hr = S_OK; INT_PTR iRet = -1;
#if (DBG == 1)
DEBUG_OUT((DEB_TRACE, "CJobFolder::_UpdateObject Validating pjidNew %x\n", pjidNew)); pjidNew->Validate(); #endif // (DBG == 1)
LPITEMIDLIST pidlCopyOfNew = ILClone((LPCITEMIDLIST)pjidNew);
if (pidlCopyOfNew == NULL) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); return hr; }
#if (DBG == 1)
DEBUG_OUT((DEB_TRACE, "CJobFolder::_UpdateObject Validating pidlCopyOfNew %x\n", pidlCopyOfNew)); ((PJOBID) pidlCopyOfNew)->Validate();
DEBUG_OUT((DEB_TRACE, "CJobFolder::_UpdateObject Validating pjidOld %x\n", pjidOld)); pjidOld->Validate(); #endif // (DBG == 1)
LPITEMIDLIST apidl[2] = {(LPITEMIDLIST)pjidOld, pidlCopyOfNew};
iRet = ShellFolderView_UpdateObject(m_hwndOwner, apidl);
if (iRet < 0) { //
// The object to update couldn't be found, so the shell won't
// take ownership of the new object, and we have to free it now.
//
ILFree(pidlCopyOfNew); pidlCopyOfNew = NULL; }
if (ppidl) { *ppidl = (LPITEMIDLIST)ShellFolderView_GetObject(m_hwndOwner, iRet); #if (DBG == 1)
if (*ppidl) { DEBUG_OUT((DEB_TRACE, "CJobFolder::_UpdateObject Validating *ppidl %x\n", *ppidl)); ((PJOBID) *ppidl)->Validate(); } else { DEBUG_OUT((DEB_TRACE, "CJobFolder::_UpdateObject *ppidl is NULL\n")); } #endif // (DBG == 1)
}
DEBUG_OUT((DEB_TRACE, "<CJobFolder::_UpdateObject\n")); return hr; }
//____________________________________________________________________________
//
// Function: JFGetJobFolder
//
// Synopsis: Create an instance of CJobFolder and return the requested
// interface.
//
// Arguments: [riid] -- IN interface needed.
// [ppvObj] -- OUT place to store the interface.
//
// Returns: HRESULT
//
// History: 1/24/1996 RaviR Created
//____________________________________________________________________________
HRESULT JFGetJobFolder( REFIID riid, LPVOID* ppvObj) { CJobFolder * pJobFolder = NULL;
HRESULT hr = CJobFolder::Create(&pJobFolder);
if (SUCCEEDED(hr)) { hr = pJobFolder->QueryInterface(riid, ppvObj);
pJobFolder->Release(); }
return hr; }
//____________________________________________________________________________
//
// Member: CJobFolder::Create
//
// History: 1/31/1996 RaviR Created
//____________________________________________________________________________
HRESULT CJobFolder::Create( CJobFolder ** ppJobFolder) { TRACE_FUNCTION(CJobFolder::Create);
HRESULT hr = OleInitialize(NULL);
CHECK_HRESULT(hr);
if (SUCCEEDED(hr)) { CJobFolder *pJobFolder;
pJobFolder = new CJobFolder();
if (pJobFolder != NULL) { *ppJobFolder = pJobFolder; hr = S_OK; } else { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr);
OleUninitialize(); } }
return hr; }
//____________________________________________________________________________
//
// Member: CJobFolder::IUnknown methods
//
// History: 1/31/1996 RaviR Created
//____________________________________________________________________________
IMPLEMENT_STANDARD_IUNKNOWN(CJobFolder);
STDMETHODIMP CJobFolder::QueryInterface(REFIID riid, LPVOID* ppvObj) { LPUNKNOWN punk = NULL;
if (IsEqualIID(IID_IUnknown, riid) || IsEqualIID(IID_IShellFolder, riid)) { punk = (IUnknown*) (IShellFolder*) this; } else if (IsEqualIID(IID_IPersistFolder, riid)) { punk = (IUnknown*) (IPersistFolder*) this; } #if (_WIN32_IE >= 0x0400)
else if (IsEqualIID(IID_IPersistFolder2, riid)) { punk = (IUnknown*) (IPersistFolder2*) this; } #endif (_WIN32_IE >= 0x0400)
else if (IsEqualIID(IID_IDropTarget, riid)) { punk = (IUnknown*) (IDropTarget*) this; } else if (IsEqualIID(IID_IRemoteComputer, riid)) { punk = (IUnknown*) (IRemoteComputer*) this; } else { *ppvObj = NULL; return E_NOINTERFACE; }
*ppvObj = punk; punk->AddRef();
return S_OK; }
//____________________________________________________________________________
//
// Member: CJobFolder::IRemoteComputer::Initialize
//
// Synopsis: This method is called when the explorer is initializing or
// enumerating the name space extension. If failure is returned
// during enumeration, the extension won't appear for this
// computer. Otherwise, the extension will appear, and should
// target the given machine.
//
// Arguments: [pwszMachine] -- IN Specifies the name of the machine to target.
// [bEnumerating] -- IN
//
// Returns: HRESULT.
//
// History: 2/21/1996 RaviR Created
//
//____________________________________________________________________________
STDMETHODIMP CJobFolder::Initialize( LPCWSTR pwszMachine, BOOL bEnumerating) { DEBUG_OUT((DEB_USER12, "CJobFolder::IRemoteComputer::Initialize<%ws>\n", pwszMachine));
HRESULT hr = S_OK; LPTSTR ptszMachine = NULL;
do { if (!pwszMachine) { hr = E_INVALIDARG; CHECK_HRESULT(hr); break; }
//
// Make a copy of the machine name.
//
#ifdef UNICODE
ptszMachine = NewDupString(pwszMachine);
if (!ptszMachine) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); break; } #else
ULONG cbMachine = 1 + 2 * wcslen(pwszMachine);
ptszMachine = new CHAR[cbMachine];
if (!ptszMachine) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); break; }
hr = UnicodeToAnsi(ptszMachine, pwszMachine, cbMachine);
if (FAILED(hr)) { CHECK_HRESULT(hr); break; } #endif // UNICODE
//
// The first thing about showing a remote folder is it must be
// a MS network or else the RegConnectregistry time out will
// take at least 20 seconds and there won't even be a MSTask
// on the machine.
if( !IsMsNetwork( ptszMachine ) ) { return E_FAIL; }
//
// We only want to show the remote jobs folder if the user has
// administrative access to that machine, and the task scheduler
// is installed there.
//
// Test both at once by trying to get a full access handle to
// the remote machine's task scheduler reg key.
//
if (bEnumerating) { //
// Check if the schedule service is registered on pwszMachine.
//
long lr = ERROR_SUCCESS; HKEY hRemoteKey = NULL; HKEY hSchedKey = NULL;
lr = RegConnectRegistry(ptszMachine, HKEY_LOCAL_MACHINE, &hRemoteKey); CHECK_LASTERROR(lr);
if (lr == ERROR_SUCCESS) { lr = RegOpenKeyEx(hRemoteKey, SCH_AGENT_KEY, 0, KEY_ALL_ACCESS, &hSchedKey); CHECK_LASTERROR(lr); }
if (hRemoteKey != NULL) { RegCloseKey(hRemoteKey); }
if (hSchedKey != NULL) { RegCloseKey(hSchedKey); }
if (lr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lr); break; } }
//
// Success; remember the machine name.
//
m_pszMachine = ptszMachine; } while (0);
if (FAILED(hr)) { delete [] ptszMachine; }
return hr; }
//____________________________________________________________________________
//
//
// Support function: MsNetwork
//
// Synopsis: Resolves whether or not we're attempting to connect to
// a MS network
//
// History: 11/12/00 DGrube Created
//
//
//____________________________________________________________________________
BOOL IsMsNetwork( LPTSTR ptszMachine ) { DWORD dwError; NETRESOURCE nr; NETRESOURCE nrOut; LPTSTR pszSystem = NULL; // pointer to variable-length strings
NETRESOURCE* lpBuffer = &nrOut; // buffer
DWORD cbResult = sizeof(nrOut); // buffer size
BOOL bReturn = TRUE;
//
// Fill a block of memory with zeroes; then
// initialize the NETRESOURCE structure.
//
ZeroMemory(&nr, sizeof(nr));
nr.dwScope = RESOURCE_GLOBALNET; nr.dwType = RESOURCETYPE_ANY; nr.lpRemoteName = ptszMachine;
//
// First call the WNetGetResourceInformation function with
// memory allocated to hold only a NETRESOURCE structure. This
// method can succeed if all the NETRESOURCE pointers are NULL.
//
dwError = WNetGetResourceInformation(&nr, lpBuffer, &cbResult, &pszSystem);
//
// If the call fails because the buffer is too small,
// call the LocalAlloc function to allocate a larger buffer.
//
if (dwError == ERROR_MORE_DATA) { lpBuffer = (NETRESOURCE*) LocalAlloc(LMEM_FIXED, cbResult);
if (lpBuffer == NULL) { CHECK_LASTERROR(GetLastError()); return FALSE; } }
//
// Call WNetGetResourceInformation again
// with the larger buffer.
//
dwError = WNetGetResourceInformation(&nr, lpBuffer, &cbResult, &pszSystem);
if (dwError == NO_ERROR) { // If the call succeeds, process the contents of the
// returned NETRESOURCE structure and the variable-length
// strings in lpBuffer. Then free the memory.
//
if ( NULL != lpBuffer->lpProvider ) { NETINFOSTRUCT NetInfo;
NetInfo.cbStructure = sizeof( NetInfo ); DWORD dwReturn = WNetGetNetworkInformation( lpBuffer->lpProvider, &NetInfo );
//
// Need to shift 16 bits for masks below because their a DWORD starting at the
// 16th bit and wNetType is a word starting at 0
//
if ( !( ( NetInfo.wNetType == ( WNNC_NET_MSNET >> 16)) || ( NetInfo.wNetType == ( WNNC_NET_LANMAN >>16) ) ) ) { bReturn = FALSE; } } else { CHECK_LASTERROR(GetLastError()); bReturn = FALSE; } } else { CHECK_LASTERROR(GetLastError()); bReturn = FALSE; }
if( NULL != lpBuffer ) { LocalFree( lpBuffer ); }
return bReturn; }
//____________________________________________________________________________
//
// Member: CJobFolder::IPersistFolder::Initialize
//
// Synopsis: same as IPersistFolder::Initialize
//
// History: 1/31/1996 RaviR Created
//____________________________________________________________________________
STDMETHODIMP CJobFolder::Initialize( LPCITEMIDLIST pidl) { TRACE(CJobFolder, IPersistFolder::Initialize);
m_pidlFldr = ILClone(pidl);
if (NULL == m_pidlFldr) { CHECK_HRESULT(E_OUTOFMEMORY);
return E_OUTOFMEMORY; }
// NOTE: if this is being invoked remotely, we assume that IRemoteComputer
// is invoked *before* IPersistFolder.
return S_OK; }
//____________________________________________________________________________
//
// Member: CJobFolder::GetClassID
//
// Synopsis: same as IPersistFolder::GetClassID
//
// History: 1/31/1996 RaviR Created
//____________________________________________________________________________
STDMETHODIMP CJobFolder::GetClassID( LPCLSID lpClassID) { TRACE(CJobFolder, GetClassID);
*lpClassID = CLSID_CJobFolder;
return S_OK; }
#if (_WIN32_IE >= 0x0400)
//+--------------------------------------------------------------------------
//
// Member: CJobFolder::IPersistFolder2::GetCurFolder
//
// Synopsis: Return a copy of the item id list for the current folder.
//
// Arguments: [ppidl] - filled with copy of pidl, or NULL on error.
//
// Returns: S_OK or E_OUTOFMEMORY
//
// Modifies: *[ppidl]
//
// History: 12-04-1997 DavidMun Created
//
//---------------------------------------------------------------------------
STDMETHODIMP CJobFolder::GetCurFolder( LPITEMIDLIST *ppidl) { TRACE(CJobFolder, GetCurFolder);
*ppidl = ILClone(m_pidlFldr);
if (NULL == *ppidl) { CHECK_HRESULT(E_OUTOFMEMORY);
return E_OUTOFMEMORY; }
// NOTE: if this is being invoked remotely, we assume that IRemoteComputer
// is invoked *before* IPersistFolder2.
return S_OK; }
#endif // (_WIN32_IE >= 0x0400)
//____________________________________________________________________________
//____________________________________________________________________________
//________________ ___________________________________
//________________ Interface IDropTarget ___________________________________
//________________ ___________________________________
//____________________________________________________________________________
//____________________________________________________________________________
//____________________________________________________________________________
//
// Member: CJobFolder::DragEnter
//
// Synopsis: same as IDropTarget::DragEnter
//
// History: 1/31/1996 RaviR Created
//____________________________________________________________________________
HRESULT CJobFolder::DragEnter( LPDATAOBJECT pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { DEBUG_OUT((DEB_TRACE, "CJobFolder::DragEnter<%x, dwEffect=%x>\n", this, *pdwEffect)); m_grfKeyStateLast = grfKeyState;
*pdwEffect = DROPEFFECT_NONE;
//
// Policy - if key TS_KEYPOLICY_DENY_DRAGDROP or DENY_CREATE_TASK
// then we won't allow this
//
if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP) || RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK)) { DEBUG_OUT((DEB_ITRACE, "Policy CREATE_TASK or DRAGDROP active - no copy operations\n"));
return S_OK; }
if (pdtobj != NULL) { LPENUMFORMATETC penum; HRESULT hr;
pdtobj->AddRef();
hr = pdtobj->EnumFormatEtc(DATADIR_GET, &penum);
if (SUCCEEDED(hr)) { FORMATETC fmte; ULONG celt;
while (penum->Next(1, &fmte, &celt) == S_OK) { if (fmte.cfFormat == CF_HDROP && (fmte.tymed & TYMED_HGLOBAL)) { // The default action is to MOVE the object. If the user
// has the CONTROL key pressed, then the operation
// becomes a copy
*pdwEffect = DROPEFFECT_MOVE;
if (grfKeyState & MK_CONTROL) { *pdwEffect = DROPEFFECT_COPY; }
break; } }
penum->Release(); }
pdtobj->Release(); }
return S_OK; }
//____________________________________________________________________________
//
// Member: CJobFolder::DragOver
//
// Synopsis: same as IDropTarget::DragOver
//
// History: 1/31/1996 RaviR Created
//____________________________________________________________________________
HRESULT CJobFolder::DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { DEBUG_OUT((DEB_TRACE, "CJobFolder::DragOver<%x, dwEffect=%d>\n", this, *pdwEffect));
*pdwEffect = DROPEFFECT_NONE;
//
// Policy - if we cannot create a task, or have no drag-drop, deny
// the request
//
if (RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP) || RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK)) { DEBUG_OUT((DEB_ITRACE, "Policy CREATE_TASK or DRAGDROP active - no copy operations\n"));
return S_OK; }
*pdwEffect = DROPEFFECT_MOVE;
if (grfKeyState & MK_CONTROL) { *pdwEffect = DROPEFFECT_COPY; }
return S_OK; }
//____________________________________________________________________________
//
// Member: CJobFolder::DragLeave
//
// Synopsis: same as IDropTarget::DragLeave
//
// History: 1/31/1996 RaviR Created
//____________________________________________________________________________
HRESULT CJobFolder::DragLeave(void) { TRACE(CJobFolder, DragLeave);
return S_OK; // Don't need to do anything here...
}
//____________________________________________________________________________
//
// Member: CJobFolder::CopyToFolder
//
// Synopsis: Performs copy of a job obect passed in to this folder
//
// Notes: If policy prevents a copy into this folder, this will
// return E_FAIL. Callers should check this if necessary.
//
// History: 1/31/1996 RaviR Created
// 4/23/1998 CameronE Modified for policy
//____________________________________________________________________________
HRESULT CJobFolder::CopyToFolder( LPDATAOBJECT pdtobj, BOOL fMove, BOOL fDragDrop, // TRUE if called as a result of a dd op.
POINTL * pPtl) // Valid for a dd op.
{ DEBUG_OUT((DEB_USER12, "CJobFolder::CopyToFolder <<----\n"));
//
// Policy - no copying into the folder if DENY_CREATE_TASK is on
// - no copying via dragdrop, either, if DENY_DRAGDROP is on
//
if (RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK) || (fDragDrop && RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP))) { DEBUG_OUT((DEB_ITRACE, "Policy CREATE_TASK or DRAGDROP active - no copy operations\n")); return E_FAIL; }
BOOL fIsDropOnSrc = ShellFolderView_IsDropOnSource(m_hwndOwner, (IDropTarget*)this);
STGMEDIUM medium; FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hr = pdtobj->GetData(&fmte, &medium);
if (FAILED(hr)) { return hr; }
HDROP hdrop = (HDROP)medium.hGlobal; UINT cFiles = DragQueryFile(hdrop, (UINT)-1, NULL, 0); BYTE * rglen = NULL; LPTSTR pFrom = NULL; UINT i; BOOL fCreatedJob = FALSE;
do { TCHAR szFileFrom[MAX_PATH+1]; UINT cchFileFrom = ARRAYSIZE(szFileFrom); BOOL fHasASchedObj = fIsDropOnSrc;
if (fHasASchedObj == FALSE) { for (i = 0; i < cFiles; i++) { DragQueryFile(hdrop, i, szFileFrom, cchFileFrom);
if (IsAScheduleObject(szFileFrom) == TRUE) { fHasASchedObj = TRUE; break; } } }
if ((fDragDrop == TRUE) && (m_grfKeyStateLast & MK_RBUTTON) && (fHasASchedObj == TRUE)) { if (_PopupRBMoveCtx(pPtl->x, pPtl->y, &fMove) == FALSE) { hr = S_FALSE; break; } }
if ((fIsDropOnSrc == TRUE) && (fMove == TRUE)) { // We don't handle positioning in the jobs folder.
hr = S_FALSE; break; }
//
// Prepare to copy jobs.
//
if (fHasASchedObj == TRUE) { rglen = new BYTE[cFiles];
if (rglen == NULL) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); break; }
ZeroMemory(rglen, cFiles * sizeof(BYTE)); }
UINT cchReqd = 1; // for an extra null char
for (i = 0; i < cFiles; i++) { DragQueryFile(hdrop, i, szFileFrom, cchFileFrom);
if ((fIsDropOnSrc == FALSE) && (IsAScheduleObject(szFileFrom) == FALSE)) { hr = CreateAJobForApp(szFileFrom); CHECK_HRESULT(hr);
if (SUCCEEDED(hr)) { fCreatedJob = TRUE; }
// continue even if an error occurs
continue; }
if (fHasASchedObj == TRUE) { rglen[i] = lstrlen(szFileFrom) + 1; cchReqd += rglen[i]; } }
hr = S_OK; // reset CreateAJobForApp might have failed
if (fHasASchedObj == FALSE) { break; }
pFrom = new TCHAR[cchReqd];
if (pFrom == NULL) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); break; }
LPTSTR pszTemp = pFrom;
for (i = 0; i < cFiles; i++) { if (rglen[i]) { DragQueryFile(hdrop, i, szFileFrom, cchFileFrom);
CopyMemory(pszTemp, szFileFrom, rglen[i] * sizeof(TCHAR));
pszTemp += rglen[i]; } }
// add extra null char
*pszTemp = TEXT('\0');
SHFILEOPSTRUCT fo = {m_hwndOwner, (fMove ? FO_MOVE : FO_COPY), pFrom, m_pszFolderPath, FOF_ALLOWUNDO | (fIsDropOnSrc ? FOF_RENAMEONCOLLISION : 0), FALSE, NULL, NULL};
if (SHFileOperation(&fo) || fo.fAnyOperationsAborted) { hr = E_FAIL; CHECK_HRESULT(hr); BREAK_ON_FAIL(hr); }
fCreatedJob = TRUE;
//
// If the drop was on the job folder shortcut, there is nothing
// else to do here.
//
if (m_hwndOwner == NULL || m_pShellView == NULL) { break; }
//
// If fIsDropOnSource then this was a copy operation from the source
// (if it was a move operation we would've already returned), the
// SHFileOperation has done the rename work for us and will
// create the files.
//
// That will produce a SHCNE_CREATE message for each dropped renamed &
// copied file. CJobFolder::HandleFsNotify will then do an _AddObject
// to put them in the UI.
//
// So in this case we need to leave before adding a bogus copy
// ourselves.
//
if (fIsDropOnSrc == TRUE) { break; }
//
// Add these items to the foldr & select them.
//
LPITEMIDLIST pidl; CJobID jid;
// First deselect any selected items
LPITEMIDLIST * ppidl;
hr = (HRESULT)ShellFolderView_GetSelectedObjects(m_hwndOwner, &ppidl);
if (SUCCEEDED(hr)) { i = ShortFromResult(hr);
while (i--) { m_pShellView->SelectItem(ppidl[i], SVSI_DESELECT); }
LocalFree(ppidl); }
for (i = 0; i < cFiles; i++) { if (rglen[i]) { DragQueryFile(hdrop, i, szFileFrom, cchFileFrom);
LPTSTR pszName = PathFindFileName(szFileFrom);
//
// If a move or copy operation includes objects which collide
// with objects already in the folder, we need to avoid
// creating a bogus duplicate in the UI for those objects.
//
if (_ObjectAlreadyPresent(pszName)) { continue; }
hr = jid.Load(m_pszFolderPath, pszName);
BREAK_ON_FAIL(hr);
hr = _AddObject(&jid, &pidl);
BREAK_ON_FAIL(hr);
m_pShellView->SelectItem(pidl, SVSI_SELECT); } }
BREAK_ON_FAIL(hr);
} while (0);
if (FAILED(hr)) { MessageBeep(MB_ICONHAND); } else if (fCreatedJob) { //
// If the drag/drop operation resulted in a new task being added
// to the tasks folder, prompt the user to start the service
// if it isn't already running.
//
if (UserCanChangeService(m_pszMachine)) { PromptForServiceStart(m_hwndOwner); } }
// clean up
delete pFrom; delete rglen; ReleaseStgMedium(&medium);
return S_OK; // Don't need to do anything here...
}
//____________________________________________________________________________
//
// Member: CJobFolder::Drop
//
// Synopsis: same as IDropTarget::Drop
//
// History: 1/31/1996 RaviR Created
//____________________________________________________________________________
HRESULT CJobFolder::Drop( LPDATAOBJECT pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect) { DEBUG_OUT((DEB_USER1, "CJobFolder::Drop <<----\n"));
*pdwEffect = DROPEFFECT_NONE;
//
// Policy - we should never get here, since we disabled
// it in DragEnter and DragOver, but just in case
//
if (RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK) || RegReadPolicyKey(TS_KEYPOLICY_DENY_DRAGDROP)) { return S_OK; }
BOOL fMove = !(grfKeyState & MK_CONTROL);
DEBUG_OUT((DEB_USER12, "CJobFolder::Drop <%s>\n", fMove ? "Move" : "Copy"));
return CopyToFolder(pdtobj, fMove, TRUE, &ptl); }
BOOL CJobFolder::_PopupRBMoveCtx( LONG x, LONG y, BOOL * pfMove) { DEBUG_OUT((DEB_USER1, "CJobFolder::_PopupRBMoveCtx\n"));
const TCHAR c_szStatic[] = TEXT("Static"); int iRet = FALSE;
HWND hwndDummy = CreateWindow(c_szStatic, NULL, 0, x, y, 1, 1, m_hwndOwner, // HWND_DESKTOP,
NULL, g_hInstance, NULL); if (hwndDummy) { HWND hwndPrev = GetForegroundWindow(); // to restore
UINT uFlags = TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTALIGN;
HMENU popup; HMENU subpopup;
popup = LoadMenu(g_hInstance, MAKEINTRESOURCE(POPUP_RBUTTON_MOVE)); subpopup = GetSubMenu(popup, 0);
SetForegroundWindow(hwndDummy); SetFocus(hwndDummy); iRet = TrackPopupMenu(subpopup, uFlags, x, y, 0, hwndDummy, NULL);
DestroyMenu(popup);
if (iRet) { // non-cancel item is selected. Make the hwndOwner foreground.
SetForegroundWindow(m_hwndOwner); SetFocus(m_hwndOwner); } else { //
// The user canceled the menu. Restore the previous foreground
// window (before destroying hwndDummy).
//
if (hwndPrev) { SetForegroundWindow(hwndPrev); } }
DestroyWindow(hwndDummy); }
switch (iRet) { case DDIDM_MOVE: *pfMove = TRUE; return TRUE;
case DDIDM_COPY: *pfMove = FALSE; return TRUE;
case 0: default: return FALSE; } }
//____________________________________________________________________________
//
// Member: CJobFolder::CreateAJobForApp
//
// Synopsis: Creates a job for the given app.
// If (pszApp != 0) job name <- app name with ext changed to job
// Else job name <- "New Job.job", with rename.
//
// Arguments: [pszApp] -- IN
//
// Returns: HRESULT
// --- E_FAIL if policy is on preventing creation. Callers
// should check this if are contingent on a job being made.
//
// History: 4/4/1996 RaviR Created
//
//____________________________________________________________________________
HRESULT CJobFolder::CreateAJobForApp( LPCTSTR pszApp) { HRESULT hr = S_OK;
//
// Policy - if we have the regkey DENY_CREATE_TASK active
// we cannot permit new jobs to be created via the ui
//
if (RegReadPolicyKey(TS_KEYPOLICY_DENY_CREATE_TASK)) { DEBUG_OUT((DEB_ITRACE, "Policy CREATE_TASK active - no drag-drop or copy/cut/paste\n")); return E_FAIL; }
CJob * pCJob = CJob::Create();
if (pCJob == NULL) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); return hr; }
#ifndef UNICODE
WCHAR wcBuf[MAX_PATH]; #endif
do { DWORD dwAddFlags = TASK_FLAG_DONT_START_IF_ON_BATTERIES | TASK_FLAG_KILL_IF_GOING_ON_BATTERIES;
hr = pCJob->SetFlags(dwAddFlags);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
//
// Create and set a default trigger for ever day at 9:00 AM, with
// no repetition.
//
TASK_TRIGGER jt; SYSTEMTIME stNow;
GetSystemTime(&stNow);
ZeroMemory(&jt, sizeof(jt));
jt.cbTriggerSize = sizeof(jt); jt.wBeginYear = stNow.wYear; jt.wBeginMonth = stNow.wMonth; jt.wBeginDay = stNow.wDay; jt.TriggerType = TASK_TIME_TRIGGER_DAILY; jt.Type.Daily.DaysInterval = 1; jt.wStartHour = 9; jt.wStartMinute = 0; jt.rgFlags = 0;
ITaskTrigger * pTrigger = NULL; WORD iTrigger = (WORD)-1;
hr = pCJob->CreateTrigger(&iTrigger, &pTrigger);
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
hr = pTrigger->SetTrigger((const PTASK_TRIGGER)&jt);
pTrigger->Release();
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
TCHAR szJob[MAX_PATH+12];
lstrcpy(szJob, m_pszFolderPath); lstrcat(szJob, TEXT("\\"));
if (pszApp != NULL) { // set the app name
#ifdef UNICODE
hr = pCJob->SetApplicationName(pszApp); #else
hr = AnsiToUnicode(wcBuf, pszApp, MAX_PATH); CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
hr = pCJob->SetApplicationName(wcBuf); #endif
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
// the job name ...
lstrcat(szJob, PathFindFileName(pszApp));
LPTSTR pszExt = PathFindExtension(szJob); lstrcpy(pszExt, TSZ_DOTJOB); } else { UINT len = lstrlen(szJob);
static int s_nLengthOK = -1;
if (s_nLengthOK == -1) { UINT uiTemp = (UINT)LoadString(g_hInstance, IDS_NEW_JOB, &szJob[len], (MAX_PATH + 12 - len));
uiTemp += len;
if (uiTemp <= MAX_PATH) { s_nLengthOK = 1; } else { s_nLengthOK = 0; } }
if (s_nLengthOK == 0) { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); CHECK_HRESULT(hr); break; }
LoadString(g_hInstance, IDS_NEW_JOB, &szJob[len], (MAX_PATH - len));
EnsureUniquenessOfFileName(szJob);
if (lstrlen(szJob) > MAX_PATH) { hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW); CHECK_HRESULT(hr); break; } }
#ifdef UNICODE
hr = pCJob->Save(szJob, FALSE); #else
hr = AnsiToUnicode(wcBuf, szJob, MAX_PATH); CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
hr = pCJob->Save(wcBuf, FALSE); #endif
CHECK_HRESULT(hr); BREAK_ON_FAIL(hr);
//
// If the drop was on the job folder shortcut, there is nothing
// else to do here.
//
if (m_hwndOwner == NULL || m_pShellView == NULL) { break; }
//
// Add the job to the job folder
//
CJobID jid;
LPTSTR pszJobName = &szJob[lstrlen(m_pszFolderPath)+1];
//*(pszJobName - 1) = TEXT('\0');
hr = jid.Load(m_pszFolderPath, pszJobName); BREAK_ON_FAIL(hr);
hr = _AddObject(&jid); BREAK_ON_FAIL(hr);
//
// If this is a new task prompt the user for rename
//
if (pszApp == NULL) { //
// Prompt the user to rename the new job.
//
if (m_pShellView != NULL) { hr = m_pShellView->SelectItem(((LPCITEMIDLIST)&jid), SVSI_EDIT);
CHECK_HRESULT(hr); } }
//BREAK_ON_FAIL(hr);
} while (0);
if (pCJob != NULL) { pCJob->Release(); }
return hr; }
int CJobFolder::_GetJobIDForTask( PJOBID *ppjid, int count, LPTSTR pszTask) { LPTSTR pszExt = PathFindExtension(pszTask); TCHAR tcSave;
if (pszExt) { tcSave = *pszExt; *pszExt = TEXT('\0'); }
//
// If the folder is empty, count is 0, so initialize iCmp to -1
// to force the return statement to indicate there was no match.
//
int iCmp = -1;
for (int i=0; i < count; i++) { #if (DBG == 1)
ppjid[i]->Validate(); #endif // (DBG == 1)
//
// Don't compare template (virtual) objects against real files.
//
if (ppjid[i]->IsTemplate()) { continue; }
iCmp = lstrcmpi(ppjid[i]->GetName(), pszTask);
if (iCmp >= 0) { break; } }
if (pszExt) { *pszExt = tcSave; }
return (iCmp == 0) ? i : -1; }
void hsort(PJOBID *ppjid, UINT cObjs);
void I_Sort(PJOBID * ppjid, UINT cObjs) { UINT i;
#if (DBG == 1)
for (i=0; i < cObjs; i++) { ppjid[i]->Validate(); } #endif // (DBG == 1)
if (cObjs < 10) { UINT k = 0; PJOBID pjid;
for (i=1; i < cObjs; i++) { for (k=i; k && (lstrcmpi(ppjid[k]->GetName(), ppjid[k-1]->GetName()) < 0); --k) { pjid = ppjid[k]; ppjid[k] = ppjid[k-1]; ppjid[k-1] = pjid; } } } else { // Heap sort
hsort(ppjid, cObjs); }
#if (DBG == 1)
for (i=0; i < cObjs; i++) { ppjid[i]->Validate(); } #endif // (DBG == 1)
}
//____________________________________________________________________________
//
// Member: CJobFolder::OnUpdateDir
//
// Synopsis: S
//
// Returns: void
//
// History: 2/20/1996 RaviR Created
//
//____________________________________________________________________________
void CJobFolder::OnUpdateDir(void) { DEBUG_OUT((DEB_USER1, "CJobFolder::OnUpdateDir <<--\n"));
HRESULT hr = S_OK;
//
// First collect all the itemids from the LPSHELLVIEW
//
int cObjs = (int) ShellFolderView_GetObjectCount(m_hwndOwner);
if (m_cObjsAlloced < cObjs) { // 40 so that it is DWORD aligned
m_cObjsAlloced = ((cObjs / 40) + 1) * 40;
//
// Allocate an extra byte per jobid to use with pbPresent flag
// array. (See below.)
//
DWORD dwBytes = m_cObjsAlloced * (sizeof(PJOBID) + 1);
if (m_pUpdateDirData == NULL) { m_pUpdateDirData = (BYTE *)GlobalAlloc(GPTR, dwBytes); } else {
BYTE * pbTemp = (BYTE *)GlobalReAlloc(m_pUpdateDirData, dwBytes, GHND);
if (pbTemp) { m_pUpdateDirData = pbTemp; } else { GlobalFree(m_pUpdateDirData); m_pUpdateDirData = NULL; } }
if (m_pUpdateDirData == NULL) { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr);
m_cObjsAlloced = 0;
return; } }
PJOBID *ppjid = (PJOBID *)m_pUpdateDirData; PBYTE pbPresent = m_pUpdateDirData + m_cObjsAlloced * sizeof(PJOBID);
ZeroMemory(pbPresent, m_cObjsAlloced * sizeof(BYTE));
for (int i=0; i < cObjs; i++) { ppjid[i] = (PJOBID)ShellFolderView_GetObject(m_hwndOwner, i); #if (DBG == 1)
ppjid[i]->Validate(); #endif
}
I_Sort(ppjid, cObjs);
//
//
//
TCHAR szSearchPath[MAX_PATH] = TEXT(""); lstrcpy(szSearchPath, m_pszFolderPath); lstrcat(szSearchPath, TEXT("\\*") TSZ_DOTJOB);
WIN32_FIND_DATA fd; HANDLE hFind = FindFirstFile(szSearchPath, &fd);
int index;
if (hFind != INVALID_HANDLE_VALUE) { CJobID jid;
while (1) { index = _GetJobIDForTask(ppjid, cObjs, fd.cFileName);
if (index < 0) { // Add item
hr = jid.Load(m_pszFolderPath, fd.cFileName);
if (hr == S_OK) { hr = _AddObject(&jid); } } else { if (CompareFileTime(&fd.ftCreationTime, &ppjid[index]->_ftCreation) || CompareFileTime(&fd.ftLastWriteTime, &ppjid[index]->_ftLastWrite)) { // update job
DEBUG_OUT((DEB_USER12, "OnUpdateDir::UPDATE_ITEM<%ws>\n", fd.cFileName));
hr = jid.Load(m_pszFolderPath, fd.cFileName);
if (hr == S_OK) { LPITEMIDLIST pidl;
hr = _UpdateObject(&jid, &jid, &pidl);
if (SUCCEEDED(hr)) { ppjid[index] = (PJOBID)pidl; }
// mark as present
pbPresent[index] = 1; } } else { // mark as present
pbPresent[index] = 1; } }
//
// Let us continue even on failure unless it is a memory error
//
if (hr == E_OUTOFMEMORY) { break; }
//
// Get the next file.
//
if (FindNextFile(hFind, &fd) == FALSE) { if (GetLastError() != ERROR_NO_MORE_FILES) { CHECK_LASTERROR(GetLastError()); }
break; } }
FindClose(hFind);
//
// Let us continue even on failure unless it is a memory error
//
if (hr != E_OUTOFMEMORY) { //
// Now delete any old items that are no longer valid, making
// sure to ignore the template object.
//
for (i=0; i < cObjs; i++) { if (!pbPresent[i] && !ppjid[i]->IsTemplate()) { // Delete object
_RemoveObject(ppjid[i]); } } } } else { if (GetLastError() != ERROR_FILE_NOT_FOUND) { CHECK_LASTERROR(GetLastError()); } else if (GetLastError() != ERROR_NO_MORE_FILES) { // delete everything but template objects
for (i=0; i < cObjs; i++) { if (!ppjid[i]->IsTemplate()) { _RemoveObject(ppjid[i]); } } } }
if (hr == E_OUTOFMEMORY) { // Display error message
}
DEBUG_OUT((DEB_USER1, "CJobFolder::OnUpdateDir -->>\n"));
return; }
|