home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 November / Chip_2003-11_cd1.bin / software / dave / dqsd.exe / src / DQSDTools / Launcher.cpp < prev    next >
C/C++ Source or Header  |  2002-10-23  |  20KB  |  743 lines

  1. // Launcher.cpp : Implementation of CLauncher
  2. #include "stdafx.h"
  3. #include "DQSDTools.h"
  4. #include "KeyboardHook.h"
  5. #include "Launcher.h"
  6. #include "Utilities.h"
  7. #include <objbase.h>
  8. #include <shlguid.h>
  9. #include <shlobj.h>
  10.  
  11. #pragma comment(lib, "Version.lib")
  12.  
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CLauncher
  15.  
  16. LPCTSTR CLauncher::DQSD_REG_KEY = _T("CLSID\\{226b64e8-dc75-4eea-a6c8-abcb4d1d37ff}");
  17. LPCTSTR CLauncher::DQSD_SEC_KEY = _T("CLSID\\{226b64e8-dc75-4eea-a6c8-abcb4d1d37ff}\\SecureFiles");
  18.  
  19.  
  20. STDMETHODIMP CLauncher::SetSite(IUnknown* pUnkSite)
  21. {
  22. #if defined(DQSD_NOSECURITY) && defined(_DEBUG)
  23. #pragma message(  __FILE__ " ** WARNING! ** Compilation without security restrictions...do not distribute the resulting binary! " )
  24. #else
  25.     USES_CONVERSION;
  26.  
  27.     HRESULT hr;
  28.  
  29.     m_spUnkSite = pUnkSite;
  30.  
  31.     CComPtr<IServiceProvider> spSrvProv;
  32.     if (FAILED(hr = GetSite(IID_IServiceProvider, (void**)&spSrvProv)))
  33.         return hr;
  34.  
  35.     CComPtr<IWebBrowser2> spWebBrowser;
  36.     if (FAILED(hr = spSrvProv->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrowser)))
  37.         return hr;
  38.  
  39.     CComBSTR bstrURL;
  40.     if (FAILED(hr = spWebBrowser->get_LocationURL(&bstrURL)))
  41.         return hr;
  42.  
  43.     HKEY hDqsdKey;
  44.     if (ERROR_SUCCESS != RegOpenKey(HKEY_CLASSES_ROOT, DQSD_SEC_KEY, &hDqsdKey))
  45.     {
  46.         Error(IDS_ERR_UNAUTHCALLER, IID_ILauncher);
  47.         return E_FAIL;
  48.     }
  49.  
  50.     
  51.     DWORD dt;
  52.     TCHAR filebuf[MAX_PATH];
  53.     DWORD filelen = sizeof(filebuf);
  54.     DWORD idw = 0;
  55.     BOOL success = FALSE;
  56.  
  57.     while (ERROR_SUCCESS == RegEnumValue(hDqsdKey, idw, filebuf, &filelen, NULL, &dt, NULL, NULL))
  58.     {
  59.         idw++;
  60.         if (URLMatchesFilename(OLE2T(bstrURL), filebuf))
  61.         {
  62.             success = TRUE;
  63.             break;
  64.         }
  65.  
  66.         filelen = sizeof(filebuf);
  67.     }
  68.  
  69.     if (success == FALSE)
  70.     {
  71.         Error(IDS_ERR_UNAUTHCALLER, IID_ILauncher);
  72.         return E_FAIL;
  73.     }
  74.  
  75. #endif
  76.  
  77.   return S_OK;
  78. };
  79.  
  80.  
  81.  
  82. STDMETHODIMP CLauncher::SubmitForm(VARIANT idForm)
  83. {
  84.     HRESULT hr;
  85.  
  86.  
  87.     // Check for correct VARIANT type
  88.     if (idForm.vt != VT_DISPATCH)
  89.     {
  90.         Error(IDS_ERR_NEEDFORMOBJECT, IID_ILauncher );
  91.         return E_INVALIDARG;
  92.     }
  93.  
  94.  
  95.     // Switch to genuine IHTMLElement Interface
  96.     CComPtr<IHTMLElement> spHTMLElement;
  97.     if (FAILED(hr = idForm.pdispVal->QueryInterface(IID_IHTMLElement, (void**)&spHTMLElement)))
  98.     {
  99.         Error(IDS_ERR_NEEDFORMOBJECT, IID_ILauncher, hr);
  100.         return hr;
  101.     }
  102.  
  103.  
  104.     // Also keep IHTMLFormElement Interface ready
  105.     CComPtr<IHTMLFormElement> spFormElement;
  106.     CComBSTR bstrFormName;
  107.     if (FAILED(hr = idForm.pdispVal->QueryInterface(IID_IHTMLFormElement, (void**)&spFormElement)))
  108.     {
  109.         Error(IDS_ERR_NEEDFORMOBJECT, IID_ILauncher, hr);
  110.         return E_INVALIDARG;
  111.     }
  112.     if (FAILED(hr = spFormElement->get_name(&bstrFormName)))
  113.     {
  114.         Error(IDS_ERR_NEEDFORMNAME, IID_ILauncher, hr);
  115.         return E_INVALIDARG;
  116.     }
  117.  
  118.  
  119.     // Retrieve FORM from DOM, manipulate target window, and get HTML text
  120.     CComBSTR bstrTarget(_T("_self"));
  121.     spFormElement->put_target(bstrTarget);
  122.     CComBSTR bstrHTML;
  123.     spHTMLElement->get_outerHTML(&bstrHTML);
  124.     
  125.  
  126.     // Dump HTML text in temp file
  127.     {
  128.         DWORD cbPath = _MAX_PATH;
  129.         DWORD dwBytesWritten;
  130.         TCHAR szPath[_MAX_PATH];
  131.         ::GetTempPath(cbPath, szPath);
  132.  
  133.         StrNCat(szPath, _T("DQSDLaunch.html"), sizeof(szPath)/sizeof(TCHAR)-_tcslen(szPath)-1);
  134.         HANDLE hFile = ::CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  135.         if (hFile == INVALID_HANDLE_VALUE)
  136.             return HRESULT_FROM_WIN32(::GetLastError());
  137.  
  138.         USES_CONVERSION;
  139.  
  140.         CComBSTR bstrOutput, bstrBanner;
  141.         bstrBanner.LoadString(IDS_BANNER);
  142.         bstrOutput.Append(_T("<html><body onload=\"document."));
  143.         bstrOutput.Append(bstrFormName);
  144.         bstrOutput.Append(_T(".submit();\">\n"));
  145.         bstrOutput.Append(bstrBanner);
  146.         bstrOutput.Append(_T("\n"));
  147.         bstrOutput.Append(bstrHTML);
  148.         bstrOutput.Append(_T("\n</body></html>\n"));
  149.         ::WriteFile(hFile, OLE2T(bstrOutput), bstrOutput.Length(), &dwBytesWritten, NULL);
  150.         ::FlushFileBuffers(hFile);
  151.  
  152.         ::CloseHandle(hFile);
  153.  
  154.  
  155.         // Open html associated application, passing DQSDLaunch.html
  156.         HINSTANCE hInstance = ::ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL);
  157.         if (reinterpret_cast<INT>(hInstance) <= 32)
  158.             return E_FAIL;
  159.     }        
  160.  
  161.     return S_OK;
  162. }
  163.  
  164.  
  165. STDMETHODIMP CLauncher::OpenDocument(BSTR strDoc, VARIANT* pvParameters)
  166. {
  167.     USES_CONVERSION;
  168.  
  169.     // Check for optional string parameter.  Any non-existent parameter should be indicated
  170.     // by a VARIANT of type VT_ERROR with a value of DISP_E_PARAMNOTFOUND.
  171.     HINSTANCE hInstance = NULL;
  172.     if (pvParameters && (VT_BSTR == pvParameters->vt))
  173.     {
  174.         hInstance = ::ShellExecute(NULL, NULL, OLE2T(strDoc), OLE2T(pvParameters->bstrVal), NULL, SW_SHOWNORMAL);
  175.     }
  176.     else
  177.     {
  178.         hInstance = ::ShellExecute(NULL, NULL, OLE2T(strDoc), NULL, NULL, SW_SHOWNORMAL);
  179.     }
  180.     if (reinterpret_cast<INT>(hInstance) <= 32)
  181.         return E_FAIL;
  182.  
  183.     return S_OK;
  184. }
  185.  
  186.  
  187.  
  188. STDMETHODIMP CLauncher::get_pathDefaultBrowser(BSTR *pVal)
  189. {
  190.     USES_CONVERSION;
  191.  
  192.     DWORD cbDocPath = _MAX_PATH;
  193.     TCHAR szDocPath[_MAX_PATH];
  194.     TCHAR szExePath[_MAX_PATH];
  195.  
  196.     // Create temp file with desired .html extension
  197.     ::GetTempPath(cbDocPath, szDocPath);
  198.     StrNCat(szDocPath, _T("DQSDLaunch.html"), sizeof(szDocPath)/sizeof(TCHAR)-_tcslen(szDocPath)-1);
  199.     HANDLE hFile = ::CreateFile(szDocPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  200.     if (hFile == INVALID_HANDLE_VALUE)
  201.         return HRESULT_FROM_WIN32(::GetLastError());
  202.     ::CloseHandle(hFile);
  203.     
  204.     // Find associated app for .html files
  205.     HINSTANCE hInstance = ::FindExecutable(szDocPath, _T(""), szExePath);
  206.     if (reinterpret_cast<INT>(hInstance) <= 32)
  207.         return E_FAIL;
  208.     
  209.     // Prepare string for shipping, and ship
  210.     *pVal = ::SysAllocString(T2OLE(szExePath));
  211.  
  212.     return S_OK;
  213. }
  214.  
  215. STDMETHODIMP CLauncher::get_Debug(VARIANT_BOOL* pbDebug)
  216. {
  217.     if (NULL == pbDebug)
  218.         return E_INVALIDARG;
  219.  
  220. #pragma warning(disable: 4310) // cast truncates constant value
  221.     *pbDebug = (m_bDebug ? VARIANT_TRUE : VARIANT_FALSE);
  222. #pragma warning(default: 4310) // cast truncates constant value
  223.  
  224.     return S_OK;
  225. }
  226.  
  227. STDMETHODIMP CLauncher::put_Debug(VARIANT_BOOL bDebug)
  228. {
  229.     m_bDebug = bDebug != VARIANT_FALSE;
  230.  
  231.     return S_OK;
  232. }
  233.  
  234.  
  235. STDMETHODIMP CLauncher::ReadFile(BSTR bstrFilename, BSTR *pbstrResult)
  236. {
  237.     USES_CONVERSION;
  238.  
  239.     // Get the full pathname after applying some defaults
  240.     TCHAR szFilename[ _MAX_PATH ];
  241.     HRESULT hr = GetFilename( W2CT( bstrFilename ), szFilename );
  242.     if ( FAILED( hr ) )
  243.         return hr;
  244.     
  245.     // Try to open the file
  246.     HANDLE hFile = ::CreateFile( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  247.     if ( INVALID_HANDLE_VALUE == hFile )
  248.         return HRESULT_FROM_WIN32(::GetLastError());
  249.  
  250.  
  251.     // Read in the string data
  252.     TCHAR szData[ 1024 ];
  253.     DWORD dwBytesRead = 0;
  254.     CComBSTR bstrResult;
  255.     do
  256.     {
  257.         memset( szData, 0, sizeof szData );
  258.         ::ReadFile( hFile, &szData, sizeof szData - 1, &dwBytesRead, NULL );
  259.         bstrResult.Append( szData );
  260.     }
  261.     while ( dwBytesRead > 0 );
  262.     ::CloseHandle( hFile );
  263.  
  264.     // Return the file data in a big string
  265.     *pbstrResult = bstrResult.Detach();
  266.  
  267.     return S_OK;
  268. }
  269.  
  270. STDMETHODIMP CLauncher::WriteFile(BSTR bstrFilename, BSTR bstrValue)
  271. {
  272.     USES_CONVERSION;
  273.  
  274.     // Get the full pathname after applying some defaults
  275.     TCHAR szFilename[ _MAX_PATH ];
  276.     HRESULT hr = GetFilename( W2CT( bstrFilename ), szFilename );
  277.     if ( FAILED( hr ) )
  278.         return hr;
  279.     
  280.     HANDLE hFile = ::CreateFile( szFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  281.     if ( INVALID_HANDLE_VALUE == hFile )
  282.         HRESULT_FROM_WIN32(::GetLastError());
  283.  
  284.     DWORD dwBytesWritten = 0;
  285.     BOOL bResult = ::WriteFile( hFile, W2CT( bstrValue ), lstrlenW( bstrValue ), &dwBytesWritten, NULL );
  286.     ::FlushFileBuffers( hFile );
  287.     ::CloseHandle( hFile );
  288.     
  289.     if ( 0 == bResult )
  290.         HRESULT_FROM_WIN32(::GetLastError());
  291.  
  292.     return S_OK;
  293. }
  294.  
  295. // Private methods
  296.  
  297. HRESULT CLauncher::GetFilename( LPCTSTR szName, LPTSTR szResult, LPCTSTR pszDefaultExt /*= _T(".txt")*/ )
  298. {
  299.     USES_CONVERSION;
  300.  
  301.     // Get the installation directory from the registry
  302.     CRegKey rk;
  303.     if ( ERROR_SUCCESS != rk.Open( HKEY_CLASSES_ROOT, DQSD_REG_KEY, KEY_READ ) )
  304.     {
  305.         Error(IDS_ERR_REGKEYNOTFOUND, IID_ILauncher);
  306.         return E_UNEXPECTED;
  307.     }
  308.  
  309.     TCHAR szInstallDir[ _MAX_PATH ];
  310.     DWORD dwCount = sizeof( szInstallDir );
  311.     if ( ERROR_SUCCESS != rk.QueryValue( szInstallDir, _T("InstallDir"), &dwCount ) )
  312.     {
  313.         Error(IDS_ERR_REGKEYNOTFOUND, IID_ILauncher);
  314.         return E_UNEXPECTED;
  315.     }
  316.  
  317.     // Add the install directory and an extension if not supplied
  318.     ::PathCombine( szResult, szInstallDir, szName );
  319.     ::PathAddExtension( szResult, pszDefaultExt );
  320.  
  321.     return S_OK;
  322. }
  323.  
  324. STDMETHODIMP CLauncher::GetProtocolHandler(BSTR bstrProtocol, BSTR *pbstrHandler)
  325. {
  326.     USES_CONVERSION;
  327.  
  328.     TCHAR szProtocolHandlerKey[ 128 ];
  329.     StrCpyN( szProtocolHandlerKey, W2T( bstrProtocol ), sizeof(szProtocolHandlerKey)/sizeof(TCHAR));
  330.     StrNCat( szProtocolHandlerKey, _T("\\shell\\open\\command"), sizeof(szProtocolHandlerKey)/sizeof(TCHAR)-lstrlenW(bstrProtocol)-1);
  331.  
  332.     TCHAR szProtocolHandler[ _MAX_PATH ];
  333.     DWORD dwCount = sizeof( szProtocolHandler );
  334.  
  335.     CRegKey rk;
  336.     if ( ( ERROR_SUCCESS != rk.Open( HKEY_CLASSES_ROOT, szProtocolHandlerKey, KEY_READ ) )
  337.          ||
  338.          ( ERROR_SUCCESS != rk.QueryValue( szProtocolHandler, _T(""), &dwCount ) ) )
  339.     {
  340.         Error(IDS_ERR_PROTOCOLNOTFOUND, IID_ILauncher);
  341.         return E_UNEXPECTED;
  342.     }
  343.  
  344.     *pbstrHandler = ::SysAllocString( T2W( szProtocolHandler ) );
  345.  
  346.     return S_OK;
  347. }
  348.  
  349. STDMETHODIMP CLauncher::GetFiles(BSTR bstrFileSpec, BSTR *pbstrFiles)
  350. {
  351.     USES_CONVERSION;
  352.  
  353.     TCHAR szFilename[ _MAX_PATH ];
  354.     HRESULT hr = GetFilename( W2CT( bstrFileSpec ), szFilename, _T("*.*") );
  355.     if ( FAILED( hr ) )
  356.     {
  357.         Error(IDS_ERR_FILENOTFOUND, IID_ILauncher, hr);
  358.         return hr;
  359.     }
  360.  
  361.     WIN32_FIND_DATA fd;
  362.     memset( &fd, 0, sizeof(fd) );
  363.     HANDLE handle = ::FindFirstFile( szFilename, &fd );
  364.     if (INVALID_HANDLE_VALUE == handle)
  365.     {
  366.         Error(IDS_ERR_FILENOTFOUND, IID_ILauncher, HRESULT_FROM_WIN32(::GetLastError()));
  367.         return HRESULT_FROM_WIN32(::GetLastError());
  368.     }
  369.  
  370.     CComBSTR bstrFiles( fd.cFileName );
  371.     while ( ::FindNextFile( handle, &fd ) )
  372.     {
  373.         if ( !StrCmp( fd.cFileName, _T(".") ) || !StrCmp( fd.cFileName, _T("..") ) )
  374.             continue;
  375.  
  376.         if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  377.             continue;
  378.  
  379.         bstrFiles.Append( _T("\n") );
  380.         bstrFiles.Append( fd.cFileName );
  381.     }
  382.  
  383.     ::FindClose(handle);
  384.  
  385.     *pbstrFiles = bstrFiles.Detach();
  386.  
  387.     return S_OK;
  388. }
  389.  
  390. //
  391. // This is nothing to do with the launcher - I've just piggybacked it on to save
  392. // creating another class/interface
  393. //
  394. STDMETHODIMP CLauncher::InstallKeyboardHook(LPDISPATCH pDispDocument)
  395. {
  396.     return KeyboardHookInstall(UtilitiesFindDQSDWindow(pDispDocument), m_hKeyboardHook);
  397. }
  398.  
  399. STDMETHODIMP CLauncher::RegisterHotKey(long hotkeyVkCode, BSTR bstrModifierName, LPDISPATCH pDispDocument)
  400. {
  401.     USES_CONVERSION;
  402.  
  403.     return KeyboardInstallHotkey(hotkeyVkCode, W2T(bstrModifierName), &m_hHotkeyNotificationWindow, pDispDocument);
  404. }
  405.  
  406. //
  407. // This allows mapping of a virtual keycode to a character code
  408. // sent with WM_CHAR in KeyboardProc.  It prevents having to modify
  409. // KeyboardProc for every mapping
  410. STDMETHODIMP CLauncher::MapKeyCode(long lVKCode, long lCharCode)
  411. {
  412.     g_mapKeyCodeToCharCode[ lVKCode ] = lCharCode;
  413.     return S_OK;
  414. }
  415.  
  416.  
  417. STDMETHODIMP CLauncher::get_VersionIsCorrect(int v1, int v2, int v3, int v4, VARIANT_BOOL *pVal)
  418. {
  419.     // Check if our version resource is same or later version than 
  420.     // the one specified by the script in v1.v2.v3.v4
  421.  
  422.     try
  423.     {
  424. //        LPVOID pVersion;
  425. //        HRSRC hVerRes;
  426. //        HGLOBAL hVerResMem;
  427.         VS_FIXEDFILEINFO* pFixInfo;
  428.  
  429.         ATLTRACE("CLauncher: Starting get_VersionIsCorrect\n");
  430.  
  431.         TCHAR moduleName[MAX_PATH+1];
  432.         GetModuleFileName(_Module.GetModuleInstance(), moduleName, MAX_PATH);
  433.         DWORD dummyZero;
  434.         DWORD versionSize = GetFileVersionInfoSize(moduleName, &dummyZero);
  435.         if(versionSize == 0)
  436.         {
  437.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  438.         }
  439.         BYTE* pData = new BYTE[versionSize];
  440.         if(pData == NULL)
  441.         {
  442.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  443.         }
  444.         if(!GetFileVersionInfo(moduleName, NULL, versionSize, pData))
  445.         {
  446.             delete [] pData;
  447.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  448.         }
  449. /*    
  450.         hVerRes = FindResource(_Module.GetResourceInstance(), MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
  451.         if(hVerRes == NULL)
  452.         {
  453.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  454.         }
  455.         hVerResMem = LoadResource (_Module.GetResourceInstance(), hVerRes) ;
  456.         if(hVerResMem == NULL)
  457.         {
  458.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  459.         }
  460.         pVersion = LockResource (hVerResMem) ;
  461.         if(pVersion == NULL)
  462.         {
  463.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  464.         }
  465. */
  466.         ATLTRACE("CLauncher: About to query value\n");
  467.  
  468.         UINT length;
  469.         pFixInfo = NULL;
  470.         if(!VerQueryValue(pData, _T("\\"), (LPVOID*)&pFixInfo, &length))
  471.         {
  472.             delete [] pData;
  473.             return Error(IDS_ERR_VERSION_RESOURCE, IID_ILauncher, E_FAIL);
  474.         }
  475.  
  476.         ATLTRACE("CLauncher: value queried\n");
  477.  
  478.         int dllV1, dllV2, dllV3, dllV4;
  479.         dllV1 = pFixInfo->dwProductVersionMS >> 16;
  480.         dllV2 = pFixInfo->dwProductVersionMS & 0xffff;
  481.         dllV3 = pFixInfo->dwProductVersionLS >> 16;
  482.         dllV4 = pFixInfo->dwProductVersionLS & 0xffff;
  483.  
  484.         ATLTRACE("CLauncher: DLL Version %d.%d.%d.%d\n", dllV1, dllV2, dllV3, dllV4);
  485.  
  486.         // Assume we're going to pass
  487. #pragma warning(disable: 4310) // cast truncates constant value
  488.         *pVal = VARIANT_TRUE;
  489. #pragma warning(default: 4310) // cast truncates constant value
  490.  
  491.         // Test the version in order from MS to LS
  492.         // This could have been done as one 64 bit comparison, but...
  493.         if(dllV1 < v1)
  494.         {
  495.             *pVal = VARIANT_FALSE;
  496.         }
  497.         else if(dllV2 < v2)
  498.         {
  499.             *pVal = VARIANT_FALSE;
  500.         }
  501.         else if(dllV3 < v3)
  502.         {
  503.             *pVal = VARIANT_FALSE;
  504.         }
  505.         else if(dllV4 < v4)
  506.         {
  507.             *pVal = VARIANT_FALSE;
  508.         }
  509.  
  510.         delete [] pData;
  511.  
  512.         return S_OK; 
  513.     }
  514.     catch(...)
  515.     {
  516.         return Error(IDS_EXCEPTION_IN_VERSION_CHECK, IID_ILauncher, E_FAIL);
  517.     }
  518. }
  519.  
  520.  
  521. __declspec(dllexport) void CALLBACK RestartExplorer(HWND hParent, HINSTANCE hInst, LPTSTR lpCmdLine, int nShow)
  522. {
  523.     UNREFERENCED_PARAMETER(hParent);
  524.     UNREFERENCED_PARAMETER(hInst);
  525.     UNREFERENCED_PARAMETER(lpCmdLine);
  526.     UNREFERENCED_PARAMETER(nShow);
  527.  
  528.     HWND hwndShell = FindWindow("Progman", NULL);
  529.     ::PostMessage(hwndShell, WM_QUIT, 0, 0L);
  530.     ::WinExec("Explorer.exe",SW_SHOW);
  531. }
  532.  
  533. DWORD WINAPI ShutdownThread(void* pParam)
  534. {
  535.     HWND hDQSDWnd = (HWND)pParam;
  536.  
  537.     // Wait for DQSD to be gone
  538.     LONG startTime = GetTickCount();
  539.     while(((LONG)GetTickCount() - startTime) < 10000)
  540.     {
  541.         if(!IsWindow(hDQSDWnd))
  542.         {
  543.             // We're gone
  544.  
  545.             // Restart Explorer
  546.             RestartExplorer(NULL,NULL,NULL,0);
  547.             return 0;
  548.         }
  549.         Sleep(100);
  550.     }
  551.     return 0;
  552. }
  553.  
  554.  
  555. STDMETHODIMP CLauncher::ShutdownBar(LPDISPATCH pDispDocument)
  556. {
  557. //    return Error(_T("Shutdown bar not implemented yet..."), IID_ILauncher, E_NOTIMPL);
  558.  
  559.  
  560.     HWND hDQSDWnd = UtilitiesFindDQSDWindow(pDispDocument);
  561.     if(hDQSDWnd == NULL)
  562.     {
  563.         return Error(_T("DQSD was not found on the taskbar"), IID_ILauncher, E_FAIL);
  564.     }
  565.  
  566.     // The window hierachy goes 
  567. //         _T("Shell_TrayWnd"), 
  568. //        _T("ReBarWindow32"), 
  569. //        _T("OCHost"), 
  570. //        _T("Shell Embedding"), 
  571. //        _T("Shell DocObject View"), 
  572. //        _T("Internet Explorer_Server") <== This is us
  573.  
  574.  
  575.     HWND hRebarBand = GetParent(GetParent(GetParent(hDQSDWnd)));
  576.     HWND hRebar = GetParent(hRebarBand);
  577.  
  578.     ATLTRACE("Rebar: 0x%x, Pane 0x%x\n", hRebar, hRebarBand);
  579.  
  580.     int nBands = ::SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0);
  581.     for(int nBand = 0; nBand < nBands; nBand++)
  582.     {
  583.         REBARBANDINFO info;
  584.         ZeroMemory(&info, sizeof(info));
  585.         info.cbSize = sizeof(info);
  586.         info.fMask = RBBIM_CHILD;
  587.  
  588.         if(::SendMessage(hRebar, RB_GETBANDINFO, nBand, (LPARAM)&info))
  589.         {
  590.             ATLTRACE("Band %d - hWnd = 0x%x\n", nBand, info.hwndChild);
  591.  
  592.             if(info.hwndChild == hRebarBand)
  593.             {
  594.                 // We've found our band - shut it down
  595.                 ::SendMessage(hRebar, RB_SHOWBAND, nBand, FALSE);
  596.                 ::SendMessage(hRebar, RB_DELETEBAND, nBand, 0);
  597.  
  598.                 ATLTRACE("Destroying band window: 0x%x\n", hRebarBand);
  599.                 DestroyWindow(hRebarBand);
  600.  
  601.                 DWORD threadId;
  602.                 ::CreateThread(NULL, 0, ShutdownThread, hDQSDWnd,0, &threadId);
  603.  
  604.                 return S_OK;
  605.             }
  606.         }
  607.     }
  608.  
  609.     return Error(_T("Failed to shut DQSD bar"), IID_ILauncher, E_FAIL);
  610. }
  611.  
  612. STDMETHODIMP CLauncher::RefreshTrayIcons()
  613. {
  614.     static DWORD result;
  615.     UINT msg = ::RegisterWindowMessage(_T("TaskbarCreated"));
  616.  
  617.     ATLTRACE("DQSDTools: Refreshing tray icons (msg 0x%x)\n", msg);
  618.  
  619.     ::SendMessageTimeout(HWND_BROADCAST, msg, 0, 0, SMTO_ABORTIFHUNG, 1000, &result);
  620.  
  621.     return S_OK;
  622. }
  623.  
  624. STDMETHODIMP CLauncher::get_InstallationDirectory(BSTR* pbstrDirectory)
  625. {
  626.     USES_CONVERSION;
  627.  
  628.     // Get the installation directory from the registry
  629.     CRegKey rk;
  630.     if ( ERROR_SUCCESS != rk.Open( HKEY_CLASSES_ROOT, DQSD_REG_KEY, KEY_READ ) )
  631.     {
  632.         Error(IDS_ERR_REGKEYNOTFOUND, IID_ILauncher);
  633.         return E_UNEXPECTED;
  634.     }
  635.  
  636.     TCHAR szInstallDir[ _MAX_PATH ];
  637.     DWORD dwCount = sizeof( szInstallDir );
  638.     if ( ERROR_SUCCESS != rk.QueryValue( szInstallDir, _T("InstallDir"), &dwCount ) )
  639.     {
  640.         Error(IDS_ERR_REGKEYNOTFOUND, IID_ILauncher);
  641.         return E_UNEXPECTED;
  642.     }
  643.     CComBSTR bstrInstallDir;
  644.     bstrInstallDir.Append(szInstallDir);
  645.     *pbstrDirectory = bstrInstallDir.Detach();
  646.     return S_OK;
  647. }
  648.  
  649. typedef struct SPECIAL_FOLDER_MAP_S {
  650.     LPCTSTR strName;
  651.     int csidl_value;
  652. } SPECIAL_FOLDER_MAP_T, *PSPECIAL_FOLDER_MAP_T, **PPSPECIAL_FOLDER_MAP_T;
  653.  
  654. static SPECIAL_FOLDER_MAP_T SpecialFolders[] =
  655. {
  656.     {"AppData",             CSIDL_APPDATA},
  657.     {"Desktop",             CSIDL_DESKTOP},
  658.     {"Favorites",           CSIDL_FAVORITES},
  659.     {"History",             CSIDL_HISTORY},
  660.     {"MyDocuments",         CSIDL_PERSONAL},
  661.     {"Recent",              CSIDL_RECENT},
  662.     {"StartMenu",           CSIDL_STARTMENU}
  663. };
  664. #define SpecialFoldersCount  (sizeof(SpecialFolders) / sizeof(SPECIAL_FOLDER_MAP_T))
  665.  
  666. STDMETHODIMP CLauncher::GetSpecialFolderLocation(BSTR bstrSpecialFolder, BSTR* pbstrLocation)
  667. {
  668.     USES_CONVERSION;
  669.     
  670.     // map from special folder name to id
  671.     BOOL bFound = FALSE;
  672.     int nFolder = 0;
  673.     LPCTSTR ptstrSpecialFolder = W2CT(bstrSpecialFolder);
  674.     for (int i=0; i < SpecialFoldersCount; i++) {
  675.         PSPECIAL_FOLDER_MAP_T pMap = &SpecialFolders[i];
  676.         if (pMap != NULL && _tcscmp(ptstrSpecialFolder, pMap->strName) == 0) {
  677.             bFound = TRUE;
  678.             nFolder = pMap->csidl_value;
  679.         }
  680.     }
  681.  
  682.  
  683.     if (!bFound) {
  684.         return E_FAIL;
  685.     }
  686.  
  687.     LPITEMIDLIST pidl;
  688.     HRESULT hr = SHGetSpecialFolderLocation(NULL, nFolder, &pidl);
  689.     if (!SUCCEEDED(hr)) {
  690.         return E_FAIL;
  691.     }
  692.  
  693.     TCHAR szPath[_MAX_PATH];
  694.     if (!::SHGetPathFromIDList(pidl, szPath)) {
  695.         return E_FAIL;
  696.     }
  697.  
  698.     CComBSTR bstrLocation;
  699.     bstrLocation.Append(szPath);
  700.     *pbstrLocation = bstrLocation.Detach();
  701.     return S_OK;
  702. }
  703.  
  704. STDMETHODIMP CLauncher::GetFolders(BSTR bstrBaseFolder, BSTR* pbstrFolders)
  705. {
  706.     USES_CONVERSION;
  707.  
  708.     TCHAR szBaseFolder[ _MAX_PATH ];
  709.     HRESULT hr = GetFilename( W2CT( bstrBaseFolder ), szBaseFolder, _T("*.*") );
  710.     if ( FAILED( hr ) )
  711.     {
  712.         Error(IDS_ERR_FILENOTFOUND, IID_ILauncher, hr);
  713.         return hr;
  714.     }
  715.  
  716.     WIN32_FIND_DATA fd;
  717.     memset( &fd, 0, sizeof(fd) );
  718.     HANDLE handle = ::FindFirstFile( szBaseFolder, &fd );
  719.     if (INVALID_HANDLE_VALUE == handle)
  720.     {
  721.         Error(IDS_ERR_FILENOTFOUND, IID_ILauncher, HRESULT_FROM_WIN32(::GetLastError()));
  722.         return HRESULT_FROM_WIN32(::GetLastError());
  723.     }
  724.  
  725.     CComBSTR bstrFolders( fd.cFileName );
  726.     while ( ::FindNextFile( handle, &fd ) )
  727.     {
  728.         if (_tcscmp(fd.cFileName, _T(".")) == 0 || _tcscmp(fd.cFileName, _T("..")) == 0)
  729.             continue;
  730.  
  731.         if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  732.             continue;
  733.  
  734.         bstrFolders.Append( _T("\n") );
  735.         bstrFolders.Append( fd.cFileName );
  736.     }
  737.  
  738.     ::FindClose(handle);
  739.  
  740.     *pbstrFolders = bstrFolders.Detach();
  741.     return S_OK;
  742. }
  743.