//____________________________________________________________________________ // // 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\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\n", uMsg)); HRESULT hr = S_OK; LRESULT lr = ERROR_SUCCESS; switch(uMsg) { case DVM_GETCCHMAX: { UINT * pcchMax = (UINT *)lParam; // + '\' + 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\n")); // } // else // { // DEBUG_OUT((DEB_USER1, "DVM_DIDDRAGDROP\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