// Connect.cpp : Implementation of CConnect #include "precomp.h" #include "AddIn.h" #include "Connect.h" #include "addin_i.c" #include "testsettingsctrl.h" #include "avrfutil.h" #include using namespace ShimLib; // Globals needed by AppVerifier wstring g_strAppName; BOOL gp_bConsoleMode; BOOL gp_bWin2KMode; BOOL g_bBreakOnLog; BOOL g_bFullPageHeap; BOOL g_bPropagateTests; extern BOOL CheckWindowsVersion(void); // // Holds the name of the active EXE. // wstring g_wstrExeName; // // Indicates if it's okay to run. // BOOL g_bCorrectOSVersion = FALSE; #define AV_OPTION_BREAK_ON_LOG L"BreakOnLog" #define AV_OPTION_FULL_PAGEHEAP L"FullPageHeap" #define AV_OPTION_AV_DEBUGGER L"UseAVDebugger" #define AV_OPTION_DEBUGGER L"Debugger" #define AV_OPTION_PROPAGATE L"PropagateTests" void pReadOptions( void ) { for (CAVAppInfo *pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); ++pApp) { LPCWSTR szExe = pApp->wstrExeName.c_str(); static const DWORD MAX_DEBUGGER_LEN = 1024; WCHAR szDebugger[MAX_DEBUGGER_LEN]; g_bBreakOnLog = pApp->bBreakOnLog = GetShimSettingDWORD(L"General", szExe, AV_OPTION_BREAK_ON_LOG, FALSE); g_bFullPageHeap = pApp->bFullPageHeap = GetShimSettingDWORD(L"General", szExe, AV_OPTION_FULL_PAGEHEAP, FALSE); pApp->bUseAVDebugger = TRUE; g_bPropagateTests = pApp->bPropagateTests = GetShimSettingDWORD(L"General", szExe, AV_OPTION_PROPAGATE, FALSE); pApp->wstrDebugger = L""; } } HPALETTE CreateDIBPalette( LPBITMAPINFO lpbmi, LPINT lpiNumColors ) { LPBITMAPINFOHEADER lpbi; LPLOGPALETTE lpPal; HANDLE hLogPal; HPALETTE hPal = NULL; int i; lpbi = (LPBITMAPINFOHEADER)lpbmi; if (lpbi->biBitCount <= 8) *lpiNumColors = (1 << lpbi->biBitCount); else *lpiNumColors = 0; // No palette needed for 24 BPP DIB if (lpbi->biClrUsed > 0) *lpiNumColors = lpbi->biClrUsed; // Use biClrUsed if (*lpiNumColors) { hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) + sizeof (PALETTEENTRY) * (*lpiNumColors)); lpPal = (LPLOGPALETTE) GlobalLock (hLogPal); lpPal->palVersion = 0x300; lpPal->palNumEntries = (WORD)*lpiNumColors; for (i = 0; i < *lpiNumColors; i++) { lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; lpPal->palPalEntry[i].peFlags = 0; } hPal = CreatePalette (lpPal); GlobalUnlock (hLogPal); GlobalFree (hLogPal); } return hPal; } HBITMAP LoadResourceBitmap( HINSTANCE hInstance, TCHAR* pszString, HPALETTE FAR* lphPalette ) { HGLOBAL hGlobal; HBITMAP hBitmapFinal = NULL; LPBITMAPINFOHEADER lpbi; HDC hdc; int iNumColors; HRSRC hRsrc = FindResource(hInstance, pszString, RT_BITMAP); if (hRsrc) { hGlobal = LoadResource(hInstance, hRsrc); lpbi = (LPBITMAPINFOHEADER)LockResource(hGlobal); hdc = GetDC(NULL); *lphPalette = CreateDIBPalette ((LPBITMAPINFO)lpbi, &iNumColors); if (*lphPalette) { SelectPalette(hdc,*lphPalette,FALSE); RealizePalette(hdc); } hBitmapFinal = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT, (LPSTR)lpbi + lpbi->biSize + iNumColors * sizeof(RGBQUAD), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS ); ReleaseDC(NULL,hdc); UnlockResource(hGlobal); FreeResource(hGlobal); } return (hBitmapFinal); } CComPtrGetPicture(PTSTR szResource) { CComPtr picture; PICTDESC pictDesc; pictDesc.cbSizeofstruct=sizeof(PICTDESC); pictDesc.picType=PICTYPE_BITMAP; pictDesc.bmp.hbitmap = LoadResourceBitmap(_Module.GetResourceInstance(), szResource, &pictDesc.bmp.hpal); OleCreatePictureIndirect(&pictDesc, IID_IPictureDisp, TRUE, (void**)(static_cast(&picture))); return picture; } // Called when the add-in is loaded into the environment. STDMETHODIMP CConnect::OnConnection( IDispatch *pApplication, AddInDesignerObjects::ext_ConnectMode ConnectMode, IDispatch *pAddInInst, SAFEARRAY ** custom ) { HRESULT hr; INITCOMMONCONTROLSEX icc; // Initialize AppVerifier settings g_strAppName = L""; gp_bConsoleMode = FALSE; gp_bWin2KMode = FALSE; g_bBreakOnLog = FALSE; g_bFullPageHeap = FALSE; g_bPropagateTests = FALSE; try { if (CheckWindowsVersion()) { g_bCorrectOSVersion = TRUE; // // Add our tests to the listview. // InitTestInfo(); // // Load the common control library and set up the link // window class. // icc.dwSize = sizeof(icc); icc.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES; InitCommonControlsEx(&icc); LinkWindow_RegisterClass(); // // Get the development environment instance and our add-in instance. // hr = pApplication->QueryInterface(__uuidof(EnvDTE::_DTE), (LPVOID*)&m_pDTE); if (FAILED(hr)) { return hr; } hr = pAddInInst->QueryInterface(__uuidof(EnvDTE::AddIn), (LPVOID*)&m_pAddInInstance); if (FAILED(hr)) { return hr; } // // OnStartupComplete contains actual connection code. // if (ConnectMode != AddInDesignerObjects::ext_cm_Startup) { return OnStartupComplete(custom); } } } // try catch(HRESULT err) { hr = err; } return hr; } // // Called when the add-in is unloaded from the environment. // STDMETHODIMP CConnect::OnDisconnection( AddInDesignerObjects::ext_DisconnectMode /*RemoveMode*/, SAFEARRAY ** /*custom*/ ) { m_pDTE.Release(); m_pAddInInstance.Release(); m_pEnableControl.Release(); m_pTestsControl.Release(); m_pOptionControl.Release(); m_pLogViewControl.Release(); return S_OK; } // // Called when there is a change to the add-in's loaded into the environment. // STDMETHODIMP CConnect::OnAddInsUpdate( SAFEARRAY ** /*custom*/ ) { // // We don't care about these changes. // return S_OK; } STDMETHODIMP CConnect::OnStartupComplete( SAFEARRAY ** /*custom*/ ) /*++ Return: S_OK on success, or an HRESULT on failure. Desc: This is called when the environment has finished loading or by OnConnection() in other instances. This is where we add our buttons to the Debug toolbar and such. --*/ { HRESULT hr = E_FAIL; CComPtr pCommands; CComPtr pCommandBars; CComPtr pDebugBar; CComPtr pOptionsCmd; CComPtr pTestsCmd; CComPtr pEnableCmd; CComPtr pLogViewCmd; CComPtr pEventSet; CComPtr pDTEEvents; CComPtr pSolutionEvents; WCHAR wszCommandId[64]; WCHAR wszCommandText[64]; WCHAR wszCommandTooltip[64]; m_solutionEventsSink.m_pParent = this; m_dteEventsSink.m_pParent = this; // // Read settings in from SDB and registry. // if (g_bCorrectOSVersion) { GetCurrentAppSettings(); pReadOptions(); } try { // // Get the main menu bars. // hr = m_pDTE->get_CommandBars(&pCommandBars); if (FAILED(hr)) { throw hr; } hr = m_pDTE->get_Commands(&pCommands); if (FAILED(hr)) { throw hr; } // // Delete existing named commands and menus. // hr = pCommands->Item(CComVariant(L"AppVerifier.Connect.Enable"), 0, &pEnableCmd); if (SUCCEEDED(hr)) { pEnableCmd->Delete(); pEnableCmd.Release(); } hr = pCommands->Item(CComVariant(L"AppVerifier.Connect.Tests"), 0, &pTestsCmd); if (SUCCEEDED(hr)) { pTestsCmd->Delete(); pTestsCmd.Release(); } hr = pCommands->Item(CComVariant(L"AppVerifier.Connect.Options"), 0, &pOptionsCmd); if (SUCCEEDED(hr)) { pOptionsCmd->Delete(); pOptionsCmd.Release(); } hr = pCommands->Item(CComVariant(L"AppVerifier.Connect.ViewLog"), 0, &pLogViewCmd); if (SUCCEEDED(hr)) { pLogViewCmd->Delete(); pLogViewCmd.Release(); } // // Get the 'Debug' toolbar. // hr = pCommandBars->get_Item(CComVariant(L"Debug"), &pDebugBar); if (FAILED(hr)) { throw hr; } // // Create the commands. These will show as buttons on the 'Debug' // toolbar. // LoadString(g_hInstance, IDS_TB_VERIFICATION_CMD_ID, wszCommandId, ARRAYSIZE(wszCommandId)); LoadString(g_hInstance, IDS_TB_VERIFICATION_CMD_TEXT, wszCommandText, ARRAYSIZE(wszCommandText)); LoadString(g_hInstance, IDS_TB_VERIFICATION_CMD_TOOLTIP, wszCommandTooltip, ARRAYSIZE(wszCommandTooltip)); // // First one is 'Verification Off'. // hr = pCommands->AddNamedCommand( m_pAddInInstance, CComBSTR(wszCommandId), CComBSTR(wszCommandText), CComBSTR(wszCommandTooltip), VARIANT_TRUE, 0, NULL, EnvDTE::vsCommandStatusSupported|EnvDTE::vsCommandStatusEnabled, &pEnableCmd); // // Add the bitmap for this button including the mask associated // with it. // if (SUCCEEDED(hr)) { hr = pEnableCmd->AddControl(pDebugBar, 1, &m_pEnableControl); if (FAILED(hr)) { throw hr; } CComQIPtrpButton(m_pEnableControl); CComPtrpicture = GetPicture(MAKEINTRESOURCE(IDB_ENABLED)); if (pButton && picture) { pButton->put_Picture(picture); CComPtrpictureMask = GetPicture(MAKEINTRESOURCE(IDB_ENABLED_MASK)); if (pictureMask) { pButton->put_Mask(pictureMask); } } } // // Second one is 'Tests'. // LoadString(g_hInstance, IDS_TB_TESTS_CMD_ID, wszCommandId, ARRAYSIZE(wszCommandId)); LoadString(g_hInstance, IDS_TB_TESTS_CMD_TEXT, wszCommandText, ARRAYSIZE(wszCommandText)); LoadString(g_hInstance, IDS_TB_TESTS_CMD_TOOLTIP, wszCommandTooltip, ARRAYSIZE(wszCommandTooltip)); hr = pCommands->AddNamedCommand( m_pAddInInstance, CComBSTR(wszCommandId), CComBSTR(wszCommandText), CComBSTR(wszCommandTooltip), VARIANT_FALSE, IDB_TESTSETTINGS_BTN, NULL, EnvDTE::vsCommandStatusSupported|EnvDTE::vsCommandStatusEnabled, &pTestsCmd); if (SUCCEEDED(hr)) { // // Add a button to the app verifier menu. // hr = pTestsCmd->AddControl(pDebugBar, 2, &m_pTestsControl); if (FAILED(hr)) { throw hr; } } // // Third one is 'Options'. // LoadString(g_hInstance, IDS_TB_OPTIONS_CMD_ID, wszCommandId, ARRAYSIZE(wszCommandId)); LoadString(g_hInstance, IDS_TB_OPTIONS_CMD_TEXT, wszCommandText, ARRAYSIZE(wszCommandText)); LoadString(g_hInstance, IDS_TB_OPTIONS_CMD_TOOLTIP, wszCommandTooltip, ARRAYSIZE(wszCommandTooltip)); hr = pCommands->AddNamedCommand( m_pAddInInstance, CComBSTR(wszCommandId), CComBSTR(wszCommandText), CComBSTR(wszCommandTooltip), VARIANT_FALSE, IDB_OPTIONS_BTN, NULL, EnvDTE::vsCommandStatusSupported|EnvDTE::vsCommandStatusEnabled, &pOptionsCmd); if (SUCCEEDED(hr)) { // // Add a button to the app verifier menu. // hr = pOptionsCmd->AddControl(pDebugBar, 3, &m_pOptionControl); if (FAILED(hr)) { throw hr; } } // // Fourth one is 'View Log.' // LoadString(g_hInstance, IDS_TB_VIEWLOG_CMD_ID, wszCommandId, ARRAYSIZE(wszCommandId)); LoadString(g_hInstance, IDS_TB_VIEWLOG_CMD_TEXT, wszCommandText, ARRAYSIZE(wszCommandText)); LoadString(g_hInstance, IDS_TB_VIEWLOG_CMD_TOOLTIP, wszCommandTooltip, ARRAYSIZE(wszCommandTooltip)); hr = pCommands->AddNamedCommand( m_pAddInInstance, CComBSTR(wszCommandId), CComBSTR(wszCommandText), CComBSTR(wszCommandTooltip), VARIANT_FALSE, IDB_VIEWLOG_BTN, NULL, EnvDTE::vsCommandStatusSupported|EnvDTE::vsCommandStatusEnabled, &pLogViewCmd); if (SUCCEEDED(hr)) { // // Add a button to the app verifier menu. // hr = pLogViewCmd->AddControl(pDebugBar, 4, &m_pLogViewControl); if (FAILED(hr)) { throw hr; } } // // Hookup to environment events. // hr = m_pDTE->get_Events(&pEventSet); if (FAILED(hr)) { throw hr; } hr = pEventSet->get_DTEEvents(&pDTEEvents); if (FAILED(hr)) { throw hr; } hr = m_dteEventsSink.DispEventAdvise((IUnknown*)pDTEEvents.p); if (FAILED(hr)) { throw hr; } hr = pEventSet->get_SolutionEvents(&pSolutionEvents); if (FAILED(hr)) { throw hr; } hr = m_solutionEventsSink.DispEventAdvise((IUnknown*)pSolutionEvents.p); if (FAILED(hr)) { throw hr; } // // Setup for current solution. // m_solutionEventsSink.Opened(); } // try catch(HRESULT err) { hr = err; } catch(...) { hr = E_FAIL; } return hr; } // // Called when the environment starts to shutdown. // STDMETHODIMP CConnect::OnBeginShutdown( SAFEARRAY ** /*custom*/ ) { return S_OK; } // // Called when the status of a command is queried. // STDMETHODIMP CConnect::QueryStatus( BSTR bstrCmdName, EnvDTE::vsCommandStatusTextWanted NeededText, EnvDTE::vsCommandStatus *pStatusOption, VARIANT * /*pvarCommandText*/) { if (NeededText == EnvDTE::vsCommandStatusTextWantedNone) { if ((_wcsicmp(bstrCmdName, L"AppVerifier.Connect.Tests")==0) || (_wcsicmp(bstrCmdName, L"AppVerifier.Connect.Options")==0)) { if (m_bEnabled) { *pStatusOption = (EnvDTE::vsCommandStatus) (EnvDTE::vsCommandStatusEnabled | EnvDTE::vsCommandStatusSupported); } else { *pStatusOption = (EnvDTE::vsCommandStatus) (EnvDTE::vsCommandStatusEnabled | EnvDTE::vsCommandStatusSupported); } } else if (_wcsicmp(bstrCmdName, L"AppVerifier.Connect.ViewLog")==0) { *pStatusOption = (EnvDTE::vsCommandStatus) (EnvDTE::vsCommandStatusEnabled | EnvDTE::vsCommandStatusSupported); } else if (_wcsicmp(bstrCmdName, L"AppVerifier.Connect.Enable")==0) { *pStatusOption = (EnvDTE::vsCommandStatus) (EnvDTE::vsCommandStatusEnabled | EnvDTE::vsCommandStatusSupported); } } return S_OK; } BOOL CALLBACK CConnect::DlgViewOptions( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { switch (message) { case WM_INITDIALOG: if (g_bBreakOnLog) { CheckDlgButton(hDlg, IDC_BREAK_ON_LOG, BST_CHECKED); } if (g_bFullPageHeap) { CheckDlgButton(hDlg, IDC_FULL_PAGEHEAP, BST_CHECKED); } if (g_bPropagateTests) { CheckDlgButton(hDlg, IDC_PROPAGATE_TESTS_TO_CHILDREN, BST_CHECKED); } return TRUE; case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_APPLY: g_bBreakOnLog = FALSE; g_bFullPageHeap = FALSE; g_bPropagateTests = FALSE; // // Determine which options the user has enabled. // if (IsDlgButtonChecked(hDlg, IDC_BREAK_ON_LOG) == BST_CHECKED) { g_bBreakOnLog = TRUE; } if (IsDlgButtonChecked(hDlg, IDC_FULL_PAGEHEAP) == BST_CHECKED) { g_bFullPageHeap = TRUE; } if (IsDlgButtonChecked(hDlg, IDC_PROPAGATE_TESTS_TO_CHILDREN) == BST_CHECKED) { g_bPropagateTests = TRUE; } ::SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); break; case PSN_QUERYCANCEL: return FALSE; } } return FALSE; } void CConnect::CreatePropertySheet( HWND hWndParent ) { CTestInfo* pTest; DWORD dwPages = 1; DWORD dwPage = 0; WCHAR wszTitle[MAX_PATH]; LPCWSTR szExe = g_wstrExeName.c_str(); // // count the number of pages // for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) { if (pTest->PropSheetPage.pfnDlgProc) { dwPages++; } } m_phPages = new HPROPSHEETPAGE[dwPages]; if (!m_phPages) { return; } // // init the global page // m_PageGlobal.dwSize = sizeof(PROPSHEETPAGE); m_PageGlobal.dwFlags = PSP_USETITLE; m_PageGlobal.hInstance = g_hInstance; m_PageGlobal.pszTemplate = MAKEINTRESOURCE(IDD_AV_OPTIONS); m_PageGlobal.pfnDlgProc = DlgViewOptions; m_PageGlobal.pszTitle = MAKEINTRESOURCE(IDS_GLOBAL_OPTIONS); m_PageGlobal.lParam = 0; m_PageGlobal.pfnCallback = NULL; m_phPages[0] = CreatePropertySheetPage(&m_PageGlobal); if (!m_phPages[0]) { // // we need the global page minimum // return; } // // add the pages for the various tests // dwPage = 1; for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) { if (pTest->PropSheetPage.pfnDlgProc) { // // we use the lParam to identify the exe involved // pTest->PropSheetPage.lParam = (LPARAM)szExe; m_phPages[dwPage] = CreatePropertySheetPage(&(pTest->PropSheetPage)); if (!m_phPages[dwPage]) { dwPages--; } else { dwPage++; } } } LoadString(g_hInstance, IDS_OPTIONS_TITLE, wszTitle, ARRAYSIZE(wszTitle)); wstring wstrOptions = wszTitle; wstrOptions += L" - "; wstrOptions += szExe; m_psh.dwSize = sizeof(PROPSHEETHEADER); m_psh.dwFlags = PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP; m_psh.hwndParent = hWndParent; m_psh.hInstance = g_hInstance; m_psh.pszCaption = wstrOptions.c_str(); m_psh.nPages = dwPages; m_psh.nStartPage = 0; m_psh.phpage = m_phPages; m_psh.pfnCallback = NULL; PropertySheet(&m_psh); } // // Called to execute a command. // STDMETHODIMP CConnect::Exec( BSTR bstrCmdName, EnvDTE::vsCommandExecOption ExecuteOption, VARIANT * /*pvarVariantIn*/, VARIANT * /*pvarVariantOut*/, VARIANT_BOOL *pvbHandled ) { HRESULT hr; CComPtr pObject; *pvbHandled = VARIANT_FALSE; if (ExecuteOption == EnvDTE::vsCommandExecOptionDoDefault) { *pvbHandled = VARIANT_TRUE; if (_wcsicmp(bstrCmdName, L"AppVerifier.Connect.Tests")==0) { CreateToolWindow(CLSID_TestSettingsCtrl); } else if (_wcsicmp(bstrCmdName, L"AppVerifier.Connect.Options")==0) { //CreateToolWindow(CLSID_AVOptions); CreatePropertySheet(NULL); } else if (_wcsicmp(bstrCmdName, L"AppVerifier.Connect.ViewLog")==0) { CreateToolWindow(CLSID_LogViewer); } else if (_wcsicmp(bstrCmdName, L"AppVerifier.Connect.Enable")==0) { m_bEnabled = !m_bEnabled; CComQIPtrpButton(m_pEnableControl); if (m_bEnabled) { SetEnabledUI(); } else { SetDisabledUI(); } GetCurrentAppSettings(); CConnect::SetCurrentAppSettings(); } else { *pvbHandled = VARIANT_FALSE; } } return S_OK; } CComPtrCConnect::GetToolWindow( CLSID clsid ) { HRESULT hr; CComPtrpWindows; CComPtrpToolWindow; CComBSTR guidPosition; hr = m_pDTE->get_Windows(&pWindows); if (FAILED(hr)) { return NULL; } if(clsid == CLSID_LogViewer) { guidPosition = L"{D39B1B7A-EFF3-42ae-8F2B-8EEE78154187}"; } else if (clsid == CLSID_TestSettingsCtrl) { guidPosition = L"{71CD7261-A72E-4a93-AB5F-3EBCFDEAE842}"; } else if (clsid == CLSID_AVOptions) { guidPosition = L"{dc878f00-ac86-4813-8ca9-384fa07cefbf}"; } else { return NULL; } hr = pWindows->Item(CComVariant(guidPosition), &pToolWindow); if (SUCCEEDED(hr)) { return pToolWindow; } else { return NULL; } } void CConnect::CreateToolWindow( const CLSID& clsid ) { HRESULT hr; CComBSTR progID; CComBSTR caption; CComBSTR guidPosition; long lMinWidth, lMinHeight; long lWidth, lHeight; BOOL bCreated = FALSE; CComPtrpObject; CComPtrpWindows; CComPtrpToolWindow; // // Bail if verifier is enabled, except for logviewer. // if (m_bEnabled && clsid != CLSID_LogViewer) { return; } // // Check if window has been already created. // pToolWindow = GetToolWindow(clsid); if (pToolWindow == NULL) { bCreated = TRUE; CComPtr picture; if(clsid == CLSID_LogViewer) { progID = L"AppVerifier.LogViewer.1"; caption = L"AppVerifier Log"; guidPosition = L"{D39B1B7A-EFF3-42ae-8F2B-8EEE78154187}"; lMinWidth = 600; lMinHeight = 400; picture = GetPicture(MAKEINTRESOURCE(IDB_VIEWLOG)); } else if (clsid == CLSID_TestSettingsCtrl) { progID = L"AppVerifier.TestSettingsCtrl.1"; caption = L"AppVerifier Test Settings"; guidPosition = L"{71CD7261-A72E-4a93-AB5F-3EBCFDEAE842}"; lMinWidth = 600; lMinHeight = 400; picture = GetPicture(MAKEINTRESOURCE(IDB_TESTSETTINGS)); } else if (clsid == CLSID_AVOptions) { progID = L"AppVerifier.AVOptions.1"; caption = L"AppVerifier Options"; guidPosition = L"{dc878f00-ac86-4813-8ca9-384fa07cefbf}"; lMinWidth = 300; lMinHeight = 100; picture = GetPicture(MAKEINTRESOURCE(IDB_OPTIONS)); } else { return; } hr = m_pDTE->get_Windows(&pWindows); if (FAILED(hr)) { return; } hr = pWindows->CreateToolWindow( m_pAddInInstance, progID, caption, guidPosition, &pObject, &pToolWindow); if (FAILED(hr)) { return; } CComQIPtrpictUnk(picture); if (pictUnk) { pToolWindow->SetTabPicture(CComVariant(pictUnk)); } } // // Make the window visible and activate it. // hr = pToolWindow->put_Visible(VARIANT_TRUE); if (FAILED(hr)) { return; } hr = pToolWindow->Activate(); if (FAILED(hr)) { return; } if (bCreated) { hr = pToolWindow->get_Width(&lWidth); if (SUCCEEDED(hr) && (lWidth < lMinWidth)) { pToolWindow->put_Width(lMinWidth); } hr = pToolWindow->get_Height(&lHeight); if (SUCCEEDED(hr) && (lHeight < lMinHeight)) { pToolWindow->put_Height(lMinHeight); } } } void CConnect::GetNativeVCExecutableNames( EnvDTE::Project* pProject ) { HRESULT hr; assert(pProject); // Get the DTE object associated with this project. CComPtr vcProjectObject; hr = pProject->get_Object(&vcProjectObject); if (SUCCEEDED(hr)) { // Cast that object to a VCProject object. CComQIPtr vcProject(vcProjectObject); if (vcProject) { // Get the configuration set associated with this project. CComPtr vcConfigSetObject; hr = vcProject->get_Configurations(&vcConfigSetObject); if (SUCCEEDED(hr)) { // Cast to IVCCollection CComQIPtr vcConfigurationSet(vcConfigSetObject); if (vcConfigurationSet) { long lVCConfigCount; hr = vcConfigurationSet->get_Count(&lVCConfigCount); if (SUCCEEDED(hr)) { // Loop through all configurations for this project. for(long j = 1; j <= lVCConfigCount; j++) { CComVariant vtConfigSetIdx(j); CComPtr vcConfigObject; hr = vcConfigurationSet->Item( vtConfigSetIdx, &vcConfigObject); if (SUCCEEDED(hr)) { CComQIPtr< VCProjectEngineLibrary:: VCConfiguration, &__uuidof(VCProjectEngineLibrary:: VCConfiguration)> vcConfig(vcConfigObject); if (vcConfig) { // First, verify that this is // a native executable. VARIANT_BOOL bIsManaged; VCProjectEngineLibrary::ConfigurationTypes configType; hr = vcConfig->get_ManagedExtensions(&bIsManaged); if (FAILED(hr)) { continue; } hr = vcConfig->get_ConfigurationType(&configType); if (FAILED(hr)) { continue; } if (configType != VCProjectEngineLibrary::typeApplication && bIsManaged != VARIANT_FALSE) { continue; } CComBSTR bstrOutput; hr = vcConfig->get_PrimaryOutput(&bstrOutput); if (SUCCEEDED(hr)) { std::wstring wsFullPath = bstrOutput; int nPos = wsFullPath.rfind(L'\\'); std::wstring wsShortName = wsFullPath.substr(nPos + 1); g_wstrExeName = wsShortName; m_sExeList.insert(wsShortName); } } } } } } } } } } BOOL CConnect::GetAppExeNames( void ) { HRESULT hr; CComPtrpSolution; CComPtrpSolBuild; CComPtrprojectSet; CComVariant varStartupProjects; m_sExeList.clear(); // // Get the current solution, there is at most one of these. // hr = m_pDTE->get_Solution(&pSolution); if (FAILED(hr)) { return FALSE; } // // Get the set of all projects in the solution. // hr = pSolution->get_Projects(&projectSet); if (FAILED(hr)) { return FALSE; } hr = pSolution->get_SolutionBuild(&pSolBuild); if (FAILED(hr)) { return FALSE; } // // Get the safe array containing all projects that will be // launched when the solution is run. // This may return nothing, if the current solution is empty. // hr = pSolBuild->get_StartupProjects(&varStartupProjects); if (FAILED(hr)){ return FALSE; } if((varStartupProjects.vt & VT_ARRAY) && (varStartupProjects.vt & VT_VARIANT)) { UINT cDim = SafeArrayGetDim(varStartupProjects.parray); if (cDim == 1) { long lowerBound, upperBound; SafeArrayGetLBound(varStartupProjects.parray, 1, &lowerBound); SafeArrayGetUBound(varStartupProjects.parray, 1, &upperBound); // Loop through the safe array, getting each startup project. for (long i = lowerBound; i <= upperBound; i++) { CComVariant vtStartupProjectName; hr = SafeArrayGetElement(varStartupProjects.parray, &i, (VARIANT*)&vtStartupProjectName); if (SUCCEEDED(hr)) { CComPtr project; hr = projectSet->Item(vtStartupProjectName,&project); if (SUCCEEDED(hr)) { GetNativeVCExecutableNames(project); } } } } } return TRUE; } BOOL CConnect::GetAppInfo( void ) { g_psTests->clear(); m_bEnabled = FALSE; if (GetAppExeNames()) { if (m_sExeList.empty()) { return FALSE; } std::set::iterator iter; iter = m_sExeList.begin(); for(; iter != m_sExeList.end(); iter++) { // // Locate this exe in the list of apps. // for (int i = 0; i < g_aAppInfo.size(); i++) { if ((*iter) == g_aAppInfo[i].wstrExeName) { m_bEnabled = TRUE; // // Add this app's tests to the set of tests to run. // CTestInfoArray::iterator test; test = g_aTestInfo.begin(); for (; test != g_aTestInfo.end(); test++) { if (g_aAppInfo[i].IsTestActive(*test)) { g_psTests->insert(test); } } break; } } } return TRUE; } SetCurrentAppSettings(); return FALSE; } void CConnect::SetEnabledUI( void ) { WCHAR wszCommandText[64]; WCHAR wszTooltip[64]; LoadString(g_hInstance, IDS_TB_VERIFY_ENABLED_TEXT, wszCommandText, ARRAYSIZE(wszCommandText)); LoadString(g_hInstance, IDS_TB_VERIFY_ENABLED_TOOLTIP, wszTooltip, ARRAYSIZE(wszTooltip)); // // Change the text on the button. // CComQIPtrpButton(m_pEnableControl); m_pEnableControl->put_Caption(CComBSTR(wszCommandText)); // // Set the picture so we show the button as enabled. // CComPtrpicture = GetPicture(MAKEINTRESOURCE(IDB_DISABLED)); pButton->put_Picture(picture); CComPtrpictureMask = GetPicture(MAKEINTRESOURCE(IDB_ENABLED_MASK)); pButton->put_Mask(pictureMask); // // Change the tooltip so that it corresponds to the change // in the button text. // m_pEnableControl->put_TooltipText(CComBSTR(wszTooltip)); m_pEnableControl->put_Enabled(VARIANT_TRUE); m_pTestsControl->put_Enabled(VARIANT_FALSE); m_pOptionControl->put_Enabled(VARIANT_FALSE); // // Hide all of our settings windows. // CComPtrpWindow; pWindow = GetToolWindow(CLSID_TestSettingsCtrl); if (pWindow) { pWindow->put_Visible(VARIANT_FALSE); } pWindow = GetToolWindow(CLSID_AVOptions); if (pWindow) { pWindow->put_Visible(VARIANT_FALSE); } } void CConnect::DisableVerificationBtn( void ) { CComQIPtrpButton(m_pEnableControl); m_pEnableControl->put_Enabled(VARIANT_FALSE); } void CConnect::EnableVerificationBtn( void ) { CComQIPtrpButton(m_pEnableControl); m_pEnableControl->put_Enabled(VARIANT_TRUE); } void CConnect::SetDisabledUI( void ) { WCHAR wszCommandText[64]; WCHAR wszTooltip[64]; LoadString(g_hInstance, IDS_TB_VERIFICATION_CMD_TEXT, wszCommandText, ARRAYSIZE(wszCommandText)); LoadString(g_hInstance, IDS_TB_VERIFICATION_CMD_TOOLTIP, wszTooltip, ARRAYSIZE(wszTooltip)); // // Change the text on the button. // CComQIPtrpButton(m_pEnableControl); m_pEnableControl->put_Caption(CComBSTR(wszCommandText)); // // Set the picture so we show the button as disabled. // CComPtr picture = GetPicture(MAKEINTRESOURCE(IDB_ENABLED)); pButton->put_Picture(picture); CComPtr pictureMask = GetPicture(MAKEINTRESOURCE(IDB_ENABLED_MASK)); pButton->put_Mask(pictureMask); // // Change the tooltip so that it corresponds to the change // in the button text. // m_pEnableControl->put_TooltipText(CComBSTR(wszTooltip)); m_pEnableControl->put_Enabled(VARIANT_TRUE); m_pTestsControl->put_Enabled(VARIANT_TRUE); m_pOptionControl->put_Enabled(VARIANT_TRUE); } void CConnect::SetCurrentAppSettings( void ) { if (m_bEnabled) { // // Insert exes into app array. // std::set::iterator exe; exe = m_sExeList.begin(); for (; exe != m_sExeList.end(); exe++) { CAVAppInfo* pApp = NULL; for (int i = 0; i < g_aAppInfo.size(); i++) { if (g_aAppInfo[i].wstrExeName==*exe) { pApp = &g_aAppInfo[i]; break; } } if (pApp == NULL) { CAVAppInfo app; app.wstrExeName = *exe; g_aAppInfo.push_back(app); pApp = &g_aAppInfo.back(); } std::set::iterator iter; iter = g_psTests->begin(); for(; iter != g_psTests->end(); iter++) { pApp->AddTest(**iter); } // // Add flags. // pApp->bBreakOnLog = g_bBreakOnLog; pApp->bFullPageHeap = g_bFullPageHeap; pApp->bUseAVDebugger = FALSE; pApp->bPropagateTests = g_bPropagateTests; pApp->wstrDebugger = L""; } } else { std::set::iterator exe; exe = m_sExeList.begin(); for (; exe != m_sExeList.end(); exe++) { CAVAppInfoArray::iterator app; app = g_aAppInfo.begin(); for (; app != g_aAppInfo.end(); app++) { if (app->wstrExeName==*exe) { // // Before we erase this app, remove all kernel tests // and write app data. // app->dwRegFlags = 0; ::SetCurrentAppSettings(); g_aAppInfo.erase(app); break; } } } } if (!g_aAppInfo.empty()) { // // Persist Options. // for (CAVAppInfo *pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); ++pApp) { LPCWSTR szExe = pApp->wstrExeName.c_str(); SaveShimSettingDWORD(L"General", szExe, AV_OPTION_BREAK_ON_LOG, (DWORD)pApp->bBreakOnLog); SaveShimSettingDWORD(L"General", szExe, AV_OPTION_FULL_PAGEHEAP, (DWORD)pApp->bFullPageHeap); SaveShimSettingDWORD(L"General", szExe, AV_OPTION_AV_DEBUGGER, (DWORD)pApp->bUseAVDebugger); SaveShimSettingDWORD(L"General", szExe, AV_OPTION_PROPAGATE, (DWORD)pApp->bPropagateTests); SaveShimSettingString(L"General", szExe, AV_OPTION_DEBUGGER, pApp->wstrDebugger.c_str()); } ::SetCurrentAppSettings(); } } HRESULT CConnect::CSolutionEventsSink::AfterClosing( void ) { // We're done, cleanup. // Disable our controls m_pParent->m_pOptionControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pTestsControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pEnableControl->put_Enabled(VARIANT_FALSE); return S_OK; } HRESULT CConnect::CSolutionEventsSink::BeforeClosing( void ) { return S_OK; } HRESULT CConnect::CSolutionEventsSink::Opened( void ) { CComPtrpSolution; CComPtrpGlobals; if (!g_bCorrectOSVersion) { m_pParent->m_pOptionControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pTestsControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pEnableControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pLogViewControl->put_Enabled(VARIANT_FALSE); return S_OK; } // // Change in config. // if (m_pParent->GetAppInfo()) { if (m_pParent->m_bEnabled) { m_pParent->SetEnabledUI(); } else { m_pParent->SetDisabledUI(); } } else { m_pParent->m_pOptionControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pTestsControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pEnableControl->put_Enabled(VARIANT_FALSE); } return S_OK; } HRESULT CConnect::CSolutionEventsSink::ProjectAdded( EnvDTE::Project* /*proj*/ ) { if (!g_bCorrectOSVersion) { m_pParent->m_pOptionControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pTestsControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pEnableControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pLogViewControl->put_Enabled(VARIANT_FALSE); return S_OK; } // // Change in config. // if (m_pParent->GetAppInfo()) { if (m_pParent->m_bEnabled) { m_pParent->SetEnabledUI(); } else { m_pParent->SetDisabledUI(); } } else { m_pParent->m_pOptionControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pTestsControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pEnableControl->put_Enabled(VARIANT_FALSE); } return S_OK; } HRESULT CConnect::CSolutionEventsSink::ProjectRemoved( EnvDTE::Project* /*proj*/ ) { if (!g_bCorrectOSVersion) { m_pParent->m_pOptionControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pTestsControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pEnableControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pLogViewControl->put_Enabled(VARIANT_FALSE); return S_OK; } // Change in config. if (m_pParent->GetAppInfo()) { if (m_pParent->m_bEnabled) { m_pParent->SetEnabledUI(); } else { m_pParent->SetDisabledUI(); } } else { m_pParent->m_pOptionControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pTestsControl->put_Enabled(VARIANT_FALSE); m_pParent->m_pEnableControl->put_Enabled(VARIANT_FALSE); } return S_OK; } HRESULT CConnect::CSolutionEventsSink::ProjectRenamed( EnvDTE::Project* /*proj*/, BSTR /*bstrOldName*/ ) { return S_OK; } HRESULT CConnect::CSolutionEventsSink::QueryCloseSolution( VARIANT_BOOL* fCancel ) { *fCancel = VARIANT_FALSE; return S_OK; } HRESULT CConnect::CSolutionEventsSink::Renamed( BSTR /*bstrOldName*/ ) { return S_OK; }