//==============================================================; // // This source code is only intended as a supplement to // existing Microsoft documentation. // // // // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR // PURPOSE. // // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. // // // //==============================================================; #include "Backgrnd.h" const GUID CBackgroundFolder::thisGuid = { 0x2974380f, 0x4c4b, 0x11d2, { 0x89, 0xd8, 0x0, 0x0, 0x21, 0x47, 0x31, 0x28 } }; const GUID CBackground::thisGuid = { 0x2974380f, 0x4c4b, 0x11d2, { 0x89, 0xd8, 0x0, 0x0, 0x21, 0x47, 0x31, 0x28 } }; #define WM_NEWOBJECT WM_APP #define WM_DISCOVERYCOMPLETE (WM_APP + 1) //============================================================== // // CBackgroundFolder implementation // // CBackgroundFolder::CBackgroundFolder() : m_pConsoleNameSpace(NULL), m_scopeitem(0), m_threadId(0), m_thread(NULL), m_running(false), m_bViewUpdated(false) { ZeroMemory(m_children, sizeof(m_children)); WNDCLASS wndClass; ZeroMemory(&wndClass, sizeof(WNDCLASS)); wndClass.lpfnWndProc = WindowProc; wndClass.lpszClassName = _T("backgroundthreadwindow"); wndClass.hInstance = g_hinst; ATOM atom = RegisterClass(&wndClass); m_backgroundHwnd = CreateWindow( _T("backgroundthreadwindow"), // pointer to registered class name NULL, // pointer to window name 0, // window style 0, // horizontal position of window 0, // vertical position of window 0, // window width 0, // window height NULL, // handle to parent or owner window NULL, // handle to menu or child-window identifier g_hinst, // handle to application instance (void *)this // pointer to window-creation data ); if (m_backgroundHwnd) SetWindowLong(m_backgroundHwnd, GWL_USERDATA, (LONG)this); InitializeCriticalSection(&m_critSect); } CBackgroundFolder::~CBackgroundFolder() { StopThread(); for (int n = 0; n < MAX_CHILDREN; n++) if (m_children[n] != NULL) delete m_children[n]; if (m_backgroundHwnd != NULL) DestroyWindow(m_backgroundHwnd); UnregisterClass(_T("backgroundthreadwindow"), NULL); DeleteCriticalSection(&m_critSect); } LRESULT CALLBACK CBackgroundFolder::WindowProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { CBackgroundFolder *pThis = (CBackgroundFolder *)GetWindowLong(hwnd, GWL_USERDATA); switch (uMsg) { case WM_NEWOBJECT: _ASSERT(pThis != NULL); pThis->AddItem(lParam); break; case WM_DISCOVERYCOMPLETE: _ASSERT(pThis != NULL); pThis->m_bViewUpdated = true; pThis->StopThread(); break; } return DefWindowProc(hwnd, uMsg, wParam, lParam); } DWORD WINAPI CBackgroundFolder::ThreadProc( LPVOID lpParameter // thread data ) { CBackgroundFolder *pThis = (CBackgroundFolder *)lpParameter; EnterCriticalSection(&pThis->m_critSect); pThis->m_running = true; LeaveCriticalSection(&pThis->m_critSect); for (int n = 0; n < MAX_CHILDREN; n++) { EnterCriticalSection(&pThis->m_critSect); bool running = pThis->m_running; LeaveCriticalSection(&pThis->m_critSect); if (running == false) return 0; PostMessage(pThis->m_backgroundHwnd, WM_NEWOBJECT, 0, n); Sleep(500); } PostMessage(pThis->m_backgroundHwnd, WM_DISCOVERYCOMPLETE, 0, 0); return 0; } void CBackgroundFolder::StartThread() { EnterCriticalSection(&m_critSect); m_thread = CreateThread(NULL, 0, ThreadProc, (void *)this, 0, &m_threadId); LeaveCriticalSection(&m_critSect); } void CBackgroundFolder::StopThread() { EnterCriticalSection(&m_critSect); m_running = false; if (m_thread != NULL) { // this is ugly, wait for 10 seconds, then kill the thread DWORD res = WaitForSingleObject(m_thread, 10000); if (res == WAIT_TIMEOUT) TerminateThread(m_thread, 0); CloseHandle(m_thread); m_thread = NULL; } LeaveCriticalSection(&m_critSect); } void CBackgroundFolder::AddItem(int id) { HRESULT hr; EnterCriticalSection(&m_critSect); _ASSERT(m_children[id] == NULL); m_children[id] = new CBackground(id); SCOPEDATAITEM sdi; // insert items here ZeroMemory(&sdi, sizeof(SCOPEDATAITEM)); sdi.mask = SDI_STR | // Displayname is valid SDI_PARAM | // lParam is valid SDI_IMAGE | // nImage is valid SDI_OPENIMAGE | // nOpenImage is valid SDI_PARENT | SDI_CHILDREN; sdi.relativeID = (HSCOPEITEM)m_scopeitem; sdi.nImage = m_children[id]->GetBitmapIndex(); sdi.nOpenImage = INDEX_OPENFOLDER; sdi.displayname = MMC_CALLBACK; sdi.lParam = (LPARAM)m_children[id]; // The cookie sdi.cChildren = 0; hr = m_pConsoleNameSpace->InsertItem( &sdi ); _ASSERT( SUCCEEDED(hr) ); m_children[id]->SetHandle(sdi.ID); LeaveCriticalSection(&m_critSect); return; } HRESULT CBackgroundFolder::OnAddImages(IImageList *pImageList, HSCOPEITEM hsi) { return pImageList->ImageListSetStrip((long *)m_pBMapSm, // pointer to a handle (long *)m_pBMapLg, // pointer to a handle 0, // index of the first image in the strip RGB(0, 128, 128) // color of the icon mask ); } HRESULT CBackgroundFolder::OnExpand(IConsoleNameSpace *pConsoleNameSpace, IConsole *pConsole, HSCOPEITEM parent) { // cache the stuff m_pConsoleNameSpace = pConsoleNameSpace; m_scopeitem = parent; if (m_bViewUpdated == false && m_running == false) StartThread(); return S_OK; } HRESULT CBackgroundFolder::OnSelect(IConsole *pConsole, BOOL bScope, BOOL bSelect) { m_bSelected = (bSelect && bScope) ? true : false; if (bSelect && !m_running) { IConsoleVerb *pConsoleVerb; HRESULT hr = pConsole->QueryConsoleVerb(&pConsoleVerb); _ASSERT(SUCCEEDED(hr)); hr = pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE); pConsoleVerb->Release(); } return S_OK; } HRESULT CBackgroundFolder::OnRefresh() { HRESULT hr = S_OK; StopThread(); EnterCriticalSection(&m_critSect); for (int n = 0; n < MAX_CHILDREN; n++) { if (m_children[n] != NULL) { HSCOPEITEM hItem = m_children[n]->GetHandle(); hr = m_pConsoleNameSpace->DeleteItem(hItem, TRUE); delete m_children[n]; m_children[n] = NULL; } } LeaveCriticalSection(&m_critSect); m_bViewUpdated = false; StartThread(); return S_OK; } const _TCHAR *CBackground::GetDisplayName(int nCol) { _TCHAR buf[128]; wsprintf(buf, _T("Background object #%d"), m_id); _TCHAR *pszCol = static_cast<_TCHAR *>(CoTaskMemAlloc((_tcslen(buf) + 1) * sizeof(_TCHAR))); _tcscpy(pszCol, buf); return pszCol; }