You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1394 lines
49 KiB
1394 lines
49 KiB
//=========================================================================
|
|
//
|
|
// File : httpwf.cxx
|
|
//
|
|
// purpose : implementation of the Cwfolders class
|
|
//
|
|
//=========================================================================
|
|
// Chad Lindhorst, 1998
|
|
|
|
#include "headers.h"
|
|
|
|
#pragma MARK_DATA(__FILE__)
|
|
#pragma MARK_CODE(__FILE__)
|
|
#pragma MARK_CONST(__FILE__)
|
|
#include "httpwfh.h"
|
|
#include "utils.hxx"
|
|
#include "iextag.h"
|
|
#include "htiface.h" // for ITargetFrame
|
|
#include "msdaipper.h" // only needed for IPP_E_SERVERTYPE_NOT_SUPPORTED
|
|
// This #define was from oledberr.h, but only shows up with some versions
|
|
// of OLEDB. (OLEDBVER = 0x210) Hopefully this is less destructive than
|
|
// setting OLEDBVER.
|
|
#define DB_E_TIMEOUT ((HRESULT)0x80040E97L)
|
|
#define DB_E_CANNOTCONNECT ((HRESULT)0x80040E96L)
|
|
#include "oledberr.h"
|
|
|
|
#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
|
|
|
|
// ========================================================================
|
|
// Cwfolders
|
|
// ========================================================================
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Members: Cwfolders::Cwfolders
|
|
// Cwfolders::~Cwfolders
|
|
//
|
|
// Synopsis: Constructor/destructor
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
Cwfolders::Cwfolders()
|
|
{
|
|
m_pSite = NULL;
|
|
m_pwb = NULL;
|
|
}
|
|
|
|
Cwfolders::~Cwfolders()
|
|
{
|
|
ReleaseInterface (m_pwb);
|
|
ReleaseInterface (m_pSite);
|
|
}
|
|
|
|
// ========================================================================
|
|
// Iwfolders
|
|
// ========================================================================
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::navigate
|
|
//
|
|
// Synopsis: Navigates the browser to a folder view of the URL passed
|
|
// in. The function requires that m_hwndOwner and m_pwb are
|
|
// both inited. (done in Cwfolders::Init)
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
Cwfolders::navigate(BSTR bstrUrl, BSTR * pbstrRetVal)
|
|
{
|
|
IUnknown* punk;
|
|
|
|
if(!m_pwb)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT hr = m_pwb->QueryInterface(IID_IUnknown, (void **) &punk);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
hr = navigateInternal(bstrUrl, NULL, /*NULL,*/ USE_NO_UI, punk);
|
|
punk->Release();
|
|
SetScriptErrorMessage (hr, pbstrRetVal);
|
|
return S_OK;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::navigateFrame
|
|
//
|
|
// Synopsis: Navigates the browser to a folder view of the URL passed
|
|
// in. This version also allows for the folder view to be
|
|
// pointed to a specific frame, as indicated by bstrTargetFrame.
|
|
// The Protocol parameter can be either "WEC","DAV", or "any"
|
|
// the latter meaning that the protocol doesn't matter.
|
|
// Protocol selection is currently an ISSUE. This requires
|
|
// the m_hwndOwner and m_pwb members to be inited.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
Cwfolders::navigateFrame(BSTR bstrUrl, BSTR bstrTargetFrame, /*BSTR bstrProtocol,*/
|
|
BSTR * pbstrRetVal)
|
|
{
|
|
IUnknown* punk;
|
|
|
|
if(!m_pwb)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT hr = m_pwb->QueryInterface(IID_IUnknown, (void **) &punk);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = navigateInternal(bstrUrl, bstrTargetFrame, /*bstrProtocol,*/ USE_NO_UI, punk);
|
|
punk->Release();
|
|
SetScriptErrorMessage (hr, pbstrRetVal);
|
|
return S_OK;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::navigateNoSite
|
|
//
|
|
// Synopsis: This does a folder navigation but doesn't require the behavior
|
|
// to be started in the normal way. (you can just call this
|
|
// with the punk. That punk should be to an object with an
|
|
// IWebBrowser2 interface.)
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
Cwfolders::navigateNoSite (BSTR bstrUrl, BSTR bstrTargetFrame, /*BSTR bstrProtocol,*/
|
|
DWORD dwhwnd, IUnknown* punk)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if ((!(m_hwndOwner = (HWND)LongToHandle(dwhwnd))) || !punk)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
// We should release any old members here
|
|
if (m_pwb)
|
|
{
|
|
ReleaseInterface (m_pwb);
|
|
m_pwb = NULL;
|
|
}
|
|
|
|
hr = punk->QueryInterface(IID_IWebBrowser2, (void **) &m_pwb);
|
|
if (FAILED (hr))
|
|
m_pwb = NULL;
|
|
|
|
if (m_pwb)
|
|
hr = navigateInternal(bstrUrl, bstrTargetFrame, /*bstrProtocol,*/ USE_ALL_UI, punk);
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
done:
|
|
return hr;
|
|
}
|
|
|
|
// ========================================================================
|
|
// IElementBehaviorSite
|
|
// ========================================================================
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::Init
|
|
//
|
|
// Synopsis: Called when this code is initialized as a behavior. This
|
|
// sets up the m_pwb, m_pSite, and m_hwndOwner members as
|
|
// well.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
Cwfolders::Init (IElementBehaviorSite __RPC_FAR *pBehaviorSite)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pBehaviorSite != NULL)
|
|
{
|
|
m_pSite = pBehaviorSite;
|
|
m_pSite->AddRef();
|
|
|
|
if (m_pwb)
|
|
{
|
|
ReleaseInterface(m_pwb);
|
|
m_pwb = NULL;
|
|
}
|
|
|
|
// gets browser window handle (for ui)
|
|
hr = GetClientSiteWindow(m_pSite, &m_hwndOwner);
|
|
if (SUCCEEDED(hr))
|
|
// Get the browser
|
|
hr = IUnknown_QueryService(m_pSite, SID_SWebBrowserApp,
|
|
IID_IWebBrowser2, (LPVOID *) &m_pwb);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::Notify
|
|
//
|
|
// Synopsis: Not really used, but needed by the interface...
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
Cwfolders::Notify (LONG lEvent, VARIANT __RPC_FAR *pVar)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
// ========================================================================
|
|
// IObjectSafety
|
|
// ========================================================================
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::SetInterfaceSafetyOptions
|
|
//
|
|
// Synopsis: Prevents those pesky security dialogs from popping up.
|
|
// We are ALWAYS secure.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
Cwfolders::SetInterfaceSafetyOptions (REFIID riid,
|
|
DWORD dwSupportedOptions, DWORD dwEnabledOptions)
|
|
{
|
|
if (riid == IID_Iwfolders)
|
|
{
|
|
// Since this object is always safe to use, no matter the input,
|
|
// this returns S_OK all the time.
|
|
return S_OK;
|
|
}
|
|
return IObjectSafetyImpl<Cwfolders>::SetInterfaceSafetyOptions (
|
|
riid, dwSupportedOptions, dwEnabledOptions);
|
|
}
|
|
|
|
// ========================================================================
|
|
// Internal helper functions
|
|
// ========================================================================
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::navigateInternal
|
|
//
|
|
// Synopsis: All the other navigate functions call this one... this is
|
|
// the one that does everything. It first creates a thread
|
|
// which will run ParseDisplayName from office. Then, it
|
|
// makes a window that will recieve messages from the new
|
|
// thread. Finally, it spends it's time in a DialogBox
|
|
// call. The normal flow is like this:
|
|
//
|
|
// PDN Thread ---------WM_WEBFOLDER_NAV----------> Message Window
|
|
// (PDN thread dies)
|
|
// Message Window -----WM_WEBFOLDER_DONE---------> Dialog Window
|
|
// (dialog and message windows close, this function returns)
|
|
//
|
|
// The dialog we put up has a cancel button though....
|
|
//
|
|
// (user hits cancel)
|
|
// Dialog Window ------WM_WEBFOLDER_CANCEL-------> MessageWindow
|
|
// MessageWindow ------WM_WEBFOLDER_DONE---------> DialogWindow
|
|
// (dialog window closes, this function returns)
|
|
// PDN Thread ---------WM_WEBFOLDER_NAV----------> MessageWindow
|
|
// (PDN thread dies and message window closes)
|
|
//
|
|
// The argsThreadArgs local variable in this function is
|
|
// used to pass information between this function, the
|
|
// message window, the dialog window, and the PDN thread.
|
|
// Be careful that this variable isn't used by more than one
|
|
// piece of code at once!!
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
Cwfolders::navigateInternal(BSTR bstrUrl, BSTR bstrTargetFrame, /*BSTR bstrProtocol,*/ int iUI, IUnknown* punk)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
DWORD dwScheme;
|
|
|
|
// This is what is used to pass all sorts of stuff between the different
|
|
// windows and threads below.
|
|
CThreadArgs argsThreadArgs;
|
|
|
|
DWORD dwThread = 0;
|
|
void * pThread = NULL;
|
|
|
|
HWND hwndMessage = 0;
|
|
|
|
WCHAR wszClassName [] = WFOLDERSWNDCLASS;
|
|
|
|
uCLSSPEC classpec;
|
|
URL_COMPONENTS urlcomp;
|
|
VARIANT vTarget;
|
|
LPITEMIDLIST pidl = NULL;
|
|
|
|
// sanity check.
|
|
if (!bstrUrl)
|
|
BAILOUT (E_INVALIDARG);
|
|
|
|
// Can't be longer than MAX_WEB_FOLDER_LENGTH
|
|
if (SysStringLen(bstrUrl) > MAX_WEB_FOLDER_LENGTH)
|
|
{
|
|
if (iUI & USE_ERROR_BOXES)
|
|
ShowError (m_hwndOwner, IDS_ERRORURLTOOLONG,
|
|
IDS_ERRORURLTOOLONGTITLE, NULL);
|
|
BAILOUT (E_INVALIDARG);
|
|
}
|
|
|
|
/*
|
|
// Check and make sure the protocol makes sense.
|
|
if (bstrProtocol && (! (0==StrCmpICW(L"wec", bstrProtocol) ||
|
|
0==StrCmpICW(L"dav", bstrProtocol) ||
|
|
0==StrCmpICW(L"any", bstrProtocol))))
|
|
{
|
|
BAILOUT (E_INVALIDARG);
|
|
}
|
|
*/
|
|
|
|
// if the url is ftp, then we are just going to assume that Office
|
|
// can't handle it. We save the user the fun of the 10 minute IOD
|
|
memset (&urlcomp, 0, sizeof(urlcomp));
|
|
urlcomp.dwStructSize = sizeof(urlcomp);
|
|
urlcomp.dwHostNameLength = 1;
|
|
urlcomp.dwUrlPathLength = 1;
|
|
urlcomp.dwExtraInfoLength = 1;
|
|
|
|
if (!InternetCrackUrlW(bstrUrl, 0, 0, &urlcomp))
|
|
BAILOUT(E_INVALIDARG);
|
|
|
|
/*
|
|
if (urlcomp.nScheme != INTERNET_SCHEME_HTTP &&
|
|
urlcomp.nScheme != INTERNET_SCHEME_HTTPS &&
|
|
bstrProtocol && (0==StrCmpICW(L"dav", bstrProtocol) ||
|
|
0==StrCmpICW(L"wec", bstrProtocol)))
|
|
{
|
|
BAILOUT(E_INVALIDARG);
|
|
}
|
|
*/
|
|
|
|
if (urlcomp.nScheme == INTERNET_SCHEME_FTP ||
|
|
urlcomp.nScheme == INTERNET_SCHEME_FILE)
|
|
{
|
|
if (iUI & USE_FAILED_QUESTION)
|
|
{
|
|
ShowNavigationFailedQuestion (bstrUrl, bstrTargetFrame);
|
|
goto done;
|
|
}
|
|
else BAILOUT(IPP_E_SERVERTYPE_NOT_SUPPORTED);
|
|
|
|
//vTarget.vt = VT_BSTR;
|
|
//vTarget.bstrVal = bstrTargetFrame;
|
|
|
|
//m_pwb->Navigate (bstrUrl, NULL, &vTarget, NULL, NULL);
|
|
//BAILOUT(S_OK);
|
|
}
|
|
|
|
|
|
// JIT install Office NSE.
|
|
// - note, do not call JIT on NT5 since it is not supported
|
|
OSVERSIONINFO osVersionInfo;
|
|
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
if (GetVersionEx(&osVersionInfo) &&
|
|
(osVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) &&
|
|
(osVersionInfo.dwMajorVersion > 4) )
|
|
{
|
|
// this is NT5, no need to call JIT
|
|
}
|
|
else
|
|
{
|
|
classpec.tyspec=TYSPEC_CLSID;
|
|
classpec.tagged_union.clsid=CLSID_IOD;
|
|
if (FAILED(FaultInIEFeature(m_hwndOwner, &classpec, NULL, 0)))
|
|
BAILOUT(S_FALSE); // this is where the script error code "CANCEL" originates
|
|
}
|
|
|
|
/****************************** DANPOZ ************************
|
|
// Give office an URL and ask for a pidl back. Do that in a
|
|
// seperate thread.
|
|
argsThreadArgs.m_hwndDialog = 0; // must be done in case
|
|
// the message thread needs to
|
|
// find out if the dialog is open
|
|
argsThreadArgs.m_bstrUrl = SysAllocString (bstrUrl);
|
|
argsThreadArgs.m_pidl = NULL;
|
|
argsThreadArgs.m_hrReady = E_FAIL;
|
|
argsThreadArgs.m_ipdnStatus = READY_WORKING;
|
|
argsThreadArgs.m_imsgStatus = READY_WORKING;
|
|
|
|
|
|
// make message window
|
|
WNDCLASSEX wcex;
|
|
|
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
|
wcex.lpfnWndProc = NavMessageProc;
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = 0;
|
|
wcex.hInstance = g_hInst;
|
|
wcex.hIcon = NULL;
|
|
wcex.hCursor = NULL;
|
|
wcex.hbrBackground = NULL;
|
|
wcex.lpszMenuName = NULL;
|
|
wcex.lpszClassName = wszClassName;
|
|
wcex.hIconSm = NULL;
|
|
|
|
RegisterClassEx(&wcex);
|
|
|
|
argsThreadArgs.m_hwndMessage = CreateWindow(wszClassName, NULL, NULL,
|
|
0, 0, 0, 0, NULL, NULL, g_hInst, NULL);
|
|
if (argsThreadArgs.m_hwndMessage == NULL)
|
|
BAILOUT (E_FAIL);
|
|
SendMessage (argsThreadArgs.m_hwndMessage, WM_WEBFOLDER_INIT, 0, (LPARAM) &argsThreadArgs);
|
|
|
|
// run Office's ParseDisplayName in a different thread. It will be
|
|
// sending messages to the argsThreadArgs.hwndMessage. It copies all
|
|
// information from that structure it needs first, then sets a flag
|
|
// which allows this procedure to deallocate the memory.
|
|
pThread = CreateThread (NULL, 0, RunParseDisplayName, &argsThreadArgs, 0, &dwThread);
|
|
|
|
if (pThread == NULL)
|
|
{
|
|
DestroyWindow (hwndMessage);
|
|
BAILOUT (E_FAIL);
|
|
}
|
|
|
|
// Wait until RunParseDisplayName makes copies of the data it needs before
|
|
// deleting it. (which would happen if the function returns)
|
|
while (argsThreadArgs.m_ipdnStatus == READY_WORKING)
|
|
Sleep(0);
|
|
|
|
// our fancy dialog (with animation!)
|
|
DialogBoxParam (g_hInst, MAKEINTRESOURCE (IDD_WEBFOLDER_SEARCH), m_hwndOwner,
|
|
WaitDlgProc, (LPARAM) &argsThreadArgs);
|
|
|
|
SetFocus (m_hwndOwner);
|
|
|
|
if (argsThreadArgs.m_imsgStatus == READY_DONE) //user didn't hit cancel
|
|
|
|
{
|
|
hr = argsThreadArgs.m_hrReady;
|
|
******************************** DANPOZ *****************************/
|
|
|
|
/******************************** DANPOZ *****************************/
|
|
hr = CreateWebFolderIDList( bstrUrl, &pidl, m_hwndOwner, punk);
|
|
/**********************************************************************/
|
|
|
|
switch (hr)
|
|
{
|
|
case S_OK:
|
|
// navigate to the pidl returned by office
|
|
// ---------------------------------------
|
|
|
|
// the message handling window packs the pidl it got from
|
|
// office (through WM_WEBFOLDER_NAV) into the .pidl of
|
|
// argsThreadArgs.
|
|
/******** ************** DANPOZ *********************
|
|
hr = NavToPidl (argsThreadArgs.m_pidl, bstrTargetFrame, m_pwb);
|
|
*****************************************************/
|
|
/*********************** DANPOZ NEW ***************/
|
|
hr = NavToPidl (pidl, bstrTargetFrame, m_pwb);
|
|
/********************************* ***************/
|
|
if (FAILED (hr))
|
|
{
|
|
hr = E_FAIL;
|
|
if (iUI & USE_WEB_PAGE_UI)
|
|
ShowNavigationFailed (m_hwndOwner, bstrUrl, bstrTargetFrame,
|
|
L"res://shdoclc.dll/http_gen.htm");
|
|
goto done;
|
|
}
|
|
else
|
|
hr = S_OK;
|
|
break;
|
|
case E_OUTOFMEMORY: //handled lower, under cleanup
|
|
break;
|
|
case MK_E_CONNECTMANUALLY: //returned to us if we sent Office an ftp or file url. Shouldn't
|
|
// happen at all (we filter those.) unless called via script
|
|
case IPP_E_SERVERTYPE_NOT_SUPPORTED:
|
|
// The server doesn't support our extensions, but does
|
|
// exist
|
|
if (iUI & USE_FAILED_QUESTION)
|
|
{
|
|
ShowNavigationFailedQuestion (bstrUrl, bstrTargetFrame);
|
|
goto done;
|
|
}
|
|
break;
|
|
case DB_SEC_E_PERMISSIONDENIED:
|
|
// authentication failed
|
|
if (iUI & USE_WEB_PAGE_UI)
|
|
ShowNavigationFailed (m_hwndOwner, bstrUrl, bstrTargetFrame,
|
|
L"res://shdoclc.dll/http_403.htm");
|
|
break;
|
|
case STG_E_ACCESSDENIED:
|
|
case STG_E_SHAREVIOLATION:
|
|
case IPP_E_OFFLINE:
|
|
hr = IPP_E_OFFLINE;
|
|
if (iUI & USE_ERROR_BOXES)
|
|
ShowError (m_hwndOwner, IDS_ERROROFFLINE,
|
|
IDS_ERROROFFLINETITLE, NULL);
|
|
break;
|
|
case DB_E_TIMEOUT:
|
|
// bind procedure timed out
|
|
if (iUI & USE_WEB_PAGE_UI)
|
|
ShowNavigationFailed (m_hwndOwner, bstrUrl, bstrTargetFrame,
|
|
L"res://shdoclc.dll/dnserror.htm");
|
|
break;
|
|
case ERROR_MOD_NOT_FOUND:
|
|
case 0x8007007e: // this value is coming back. VC 6 looks it up like
|
|
// ERROR_MOD_NOT_FOUND which is really what happened
|
|
// (office wasn't there) But ERROR_MOD_NOT_FOUND
|
|
// has a different number.
|
|
// This gets called when the IOD passes, but the namespace
|
|
// extension isn't there. This should never get called.
|
|
hr = E_FAIL;
|
|
break;
|
|
case MK_E_SYNTAX:
|
|
case MK_E_NOOBJECT:
|
|
case MK_E_UNAVAILABLE:
|
|
case MK_E_NOSTORAGE:
|
|
case E_INVALIDARG:
|
|
//hr = MK_E_NOOBJECT;
|
|
//if (iUI & USE_WEB_PAGE_UI)
|
|
// ShowNavigationFailed (m_hwndOwner, bstrUrl, bstrTargetFrame,
|
|
// L"res://shdoclc.dll/dnserror.htm");
|
|
//break;
|
|
|
|
//ISSUE - hack follows for bug 47127 - We "should" catch most real
|
|
// invalid args in the param checking at the beginning of this method,
|
|
// but forcing hr to IPP_E_SERVERTYPE_NOT_SUPPORTED makes it impossible to
|
|
// detect a real invalid arg situation that we missed above (i.e. targetframe)
|
|
hr = IPP_E_SERVERTYPE_NOT_SUPPORTED; //Force correct error code for script
|
|
|
|
//Fall through as per bug 43338
|
|
default:
|
|
#ifdef NONB2_HACK
|
|
hr = E_FAIL;
|
|
// Something went wrong, we know not what. Give a relatively
|
|
// general error page.
|
|
if (iUI & USE_WEB_PAGE_UI)
|
|
ShowNavigationFailed (m_hwndOwner, bstrUrl, bstrTargetFrame,
|
|
L"res://shdoclc.dll/http_gen.htm");
|
|
goto done;
|
|
break;
|
|
#else
|
|
// For beta 2 (bug 43338) we're going to
|
|
if (iUI & USE_FAILED_QUESTION)
|
|
{
|
|
ShowNavigationFailedQuestion (bstrUrl, bstrTargetFrame);
|
|
goto done;
|
|
}
|
|
break;
|
|
#endif
|
|
}
|
|
/****************** DANPOZ ***************************
|
|
}
|
|
else
|
|
hr = S_FALSE;
|
|
******************************************************/
|
|
|
|
cleanup:
|
|
if (hr == E_OUTOFMEMORY)
|
|
if (iUI & USE_ERROR_BOXES)
|
|
ShowError (m_hwndOwner, IDS_ERROROUTOFMEMORY,
|
|
IDS_ERROROUTOFMEMORYTITLE, NULL);
|
|
if (hr == E_FAIL)
|
|
if (iUI & USE_ERROR_BOXES)
|
|
ShowError (m_hwndOwner, IDS_ERRORINTERNAL,
|
|
IDS_ERRORINTTITLE, NULL);
|
|
if (hr == E_INVALIDARG)
|
|
if (iUI & USE_WEB_PAGE_UI)
|
|
ShowNavigationFailed (m_hwndOwner, bstrUrl, bstrTargetFrame,
|
|
L"res://shdoclc.dll/http_gen.htm");
|
|
|
|
done:
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::ShowNavigationFailedQuestion
|
|
//
|
|
// Synopsis: This is what we want to call when we can't get a folder
|
|
// view of the resource, but we might be able to get a file
|
|
// view (normal). This asks the user if he/she wants us to
|
|
// try. Navigates to the target frame.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
void
|
|
Cwfolders::ShowNavigationFailedQuestion (BSTR bstrUrl, BSTR bstrTargetFrame)
|
|
{
|
|
VARIANT vEMPTY;
|
|
VariantInit (&vEMPTY);
|
|
VARIANT * PVAREMPTY = &vEMPTY;
|
|
|
|
WCHAR wszMessage [MAX_LOADSTRING+1];
|
|
WCHAR wszTitle [MAX_LOADSTRING+1];
|
|
|
|
LoadString(g_hInst, IDS_ERRORBADSERVER, wszMessage, ARRAYSIZE(wszMessage));
|
|
LoadString(g_hInst, IDS_ERRORBADSERVERTITLE, wszTitle, ARRAYSIZE(wszTitle));
|
|
WCHAR * wsErrorMessage = new WCHAR [MAX_LOADSTRING+wcslen(bstrUrl)+1];
|
|
if (!wsErrorMessage)
|
|
{
|
|
ShowError (m_hwndOwner, IDS_ERROROUTOFMEMORY,
|
|
IDS_ERROROUTOFMEMORYTITLE, NULL);
|
|
delete[] wsErrorMessage;
|
|
return;
|
|
}
|
|
wnsprintf (wsErrorMessage, MAX_LOADSTRING+wcslen(bstrUrl), wszMessage, bstrUrl);
|
|
int iButton = MessageBox (m_hwndOwner,
|
|
wsErrorMessage,
|
|
wszTitle,
|
|
MB_YESNO | MB_ICONQUESTION);
|
|
delete[] wsErrorMessage;
|
|
if (iButton == IDYES)
|
|
{
|
|
VARIANT vTarget;
|
|
vTarget.vt = VT_BSTR;
|
|
vTarget.bstrVal = bstrTargetFrame;
|
|
|
|
m_pwb->Navigate (bstrUrl, NULL, &vTarget, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::NavToPidl
|
|
//
|
|
// Synopsis: Comparatively low level helper function that navigates
|
|
// a given pidl (from office) to the target frame given.
|
|
// The web browser 2 arg does not have to refer to the
|
|
// correct frame.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
Cwfolders::NavToPidl (LPITEMIDLIST pidl, BSTR bstrTargetFrame, IWebBrowser2 * pwb)
|
|
{
|
|
VARIANT vPidl;
|
|
HRESULT hr;
|
|
IWebBrowser2 * pwbf = NULL;
|
|
ITargetFrame * ptf = NULL;
|
|
IUnknown * punknown = NULL;
|
|
VARIANT vEMPTY;
|
|
VariantInit (&vEMPTY);
|
|
VARIANT * PVAREMPTY = &vEMPTY;
|
|
|
|
hr = InitVARIANTFromPidl(&vPidl, pidl);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// This is here to change frames, or to make a new one as the case my
|
|
if (bstrTargetFrame && (0!=StrCmpICW(L"", bstrTargetFrame)))
|
|
{
|
|
hr = pwb->QueryInterface(IID_ITargetFrame, (void **)&ptf);
|
|
FAILONBAD_HR(hr);
|
|
hr = ptf->FindFrame (bstrTargetFrame, (IUnknown *) pwb, 0, &punknown);
|
|
if (FAILED (hr))
|
|
{
|
|
hr = CreateTargetFrame (bstrTargetFrame, &punknown);
|
|
}
|
|
FAILONBAD_HR(hr);
|
|
hr = punknown->QueryInterface(IID_IWebBrowser2, (void **)&pwbf);
|
|
FAILONBAD_HR(hr);
|
|
}
|
|
else
|
|
{
|
|
pwbf = pwb;
|
|
}
|
|
|
|
// the actual navigation!
|
|
hr = pwbf->put_Visible (VARIANT_TRUE);
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
pwbf->Stop();
|
|
hr = pwbf->Navigate2(&vPidl, PVAREMPTY, PVAREMPTY, PVAREMPTY, PVAREMPTY);
|
|
}
|
|
cleanup:
|
|
ReleaseInterface (ptf);
|
|
if (pwb != pwbf)
|
|
ReleaseInterface (pwbf);
|
|
ReleaseInterface (punknown);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::RunParseDisplayName
|
|
//
|
|
// Synopsis: Runs ParseDisplayName. This is abstracted to use as a
|
|
// seperate thread.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
DWORD WINAPI
|
|
Cwfolders::RunParseDisplayName (LPVOID pArguments)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
CThreadArgs *pInfo = (CThreadArgs *)pArguments;
|
|
LPITEMIDLIST pidl = NULL;
|
|
HWND hwndMessage = pInfo->m_hwndMessage;
|
|
BSTR bstrUrl = SysAllocString (pInfo->m_bstrUrl);
|
|
|
|
// This will signal that pInfo is safe to be released (we have all the info
|
|
// we need out of it) pInfo should NEVER be referenced in this function
|
|
// after this value is set.
|
|
pInfo->m_ipdnStatus = READY_INITIALIZED;
|
|
|
|
if (!bstrUrl)
|
|
{
|
|
PostMessage (hwndMessage, WM_WEBFOLDER_NAV, 0, (LPARAM) E_OUTOFMEMORY);
|
|
goto cleanup;
|
|
}
|
|
|
|
// calls the appropriate ParseDisplayName
|
|
/******************DANPOZ*********************
|
|
hr = CreateWebFolderIDList(bstrUrl, &pidl);
|
|
**********************************************/
|
|
// because of some OLE restrictions, this call must be PostMesage,
|
|
// not SendMessage.
|
|
PostMessage (hwndMessage, WM_WEBFOLDER_NAV, (WPARAM) pidl, (LPARAM) hr);
|
|
|
|
cleanup:
|
|
SysFreeString (bstrUrl);
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// NAME: Cwfolders::WaitDlgProc
|
|
//
|
|
// SYNOPSIS: This is the handler for our little dialog. It will get
|
|
// a WM_WEBFOLDER_DONE message when it should die.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
INT_PTR CALLBACK
|
|
Cwfolders::WaitDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CThreadArgs * pInfo = NULL;
|
|
HWND hAnimation;
|
|
HWND hStatic;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_COMMAND:
|
|
if (LOWORD(wParam) == IDCANCEL)
|
|
{
|
|
pInfo = (CThreadArgs *) GetProp (hDlg, __INFO);
|
|
if (!pInfo)
|
|
return E_FAIL;
|
|
PostMessage (pInfo->m_hwndMessage, WM_WEBFOLDER_CANCEL, 0, 0);
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_INITDIALOG:
|
|
if (!lParam)
|
|
return E_INVALIDARG;
|
|
pInfo = (CThreadArgs *) lParam;
|
|
// if this is true then there is no message window (PDN thread closed
|
|
// it before we could even start the wait dialog.) Just close the
|
|
// dialog because everything is already done.
|
|
if (pInfo->m_imsgStatus == READY_DONE)
|
|
EndDialog (hDlg, 0);
|
|
else
|
|
{
|
|
if (!SetProp (hDlg, __INFO, (void *)lParam))
|
|
return E_FAIL;
|
|
// Change our text string to something with the URL in it.
|
|
// If this section fails for any reason, the dialog will keep
|
|
// the generic "IE is looking for your folder" message.
|
|
{
|
|
WCHAR wsMessage [MAX_LOADSTRING+1];
|
|
WCHAR *wsStatus = new WCHAR[wcslen(pInfo->m_bstrUrl)+1+MAX_LOADSTRING];
|
|
if (wsStatus)
|
|
{
|
|
LoadString ( g_hInst, IDS_WEBFOLDER_FIND, wsMessage, ARRAYSIZE(wsMessage) );
|
|
|
|
DWORD dwResultSize;
|
|
WCHAR wsResult [INTERNET_MAX_URL_LENGTH];
|
|
|
|
if (SUCCEEDED (CoInternetParseUrl(pInfo->m_bstrUrl, PARSE_DOMAIN,
|
|
0, wsResult, ARRAYSIZE(wsResult), &dwResultSize, 0)))
|
|
{
|
|
wnsprintf (wsStatus, wcslen(pInfo->m_bstrUrl)+MAX_LOADSTRING,
|
|
wsMessage, wsResult);
|
|
hStatic = GetDlgItem (hDlg, IDC_WEBFOLDER_MESSAGE);
|
|
if (hStatic)
|
|
SendMessage (hStatic, WM_SETTEXT, 0, (LPARAM) wsStatus);
|
|
}
|
|
|
|
delete[] wsStatus;
|
|
}
|
|
}
|
|
// At this point, we are ready to get messages from the
|
|
// message window, so let it know our hwnd.
|
|
pInfo->m_hwndDialog = hDlg;
|
|
hAnimation = GetDlgItem (hDlg, IDC_WEBFOLDER_ANIMATE);
|
|
if (hAnimation)
|
|
Animate_Open(hAnimation, MAKEINTRESOURCE(IDA_ISEARCH));
|
|
}
|
|
return S_OK;
|
|
|
|
case WM_WEBFOLDER_DONE:
|
|
// The message window is closing us.
|
|
EndDialog (hDlg, 0);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
hAnimation = GetDlgItem (hDlg, IDC_WEBFOLDER_ANIMATE);
|
|
if (hAnimation)
|
|
{
|
|
Animate_Close(hAnimation);
|
|
}
|
|
RemoveProp (hDlg, __INFO);
|
|
break;
|
|
}
|
|
return DefWindowProc(hDlg, message, wParam, lParam);
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// NAME: Cwfolders::NavMessageProc
|
|
//
|
|
// SYNOPSIS: This is the message handler for the ParseDisplayName call.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
INT_PTR CALLBACK
|
|
Cwfolders::NavMessageProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CThreadArgs * pInfo = NULL;
|
|
HANDLE hCancel;
|
|
HWND hwndDialog;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_CREATE:
|
|
if (!SetProp (hDlg, __CANCEL, STATUS_READY))
|
|
return E_FAIL;
|
|
return S_OK;
|
|
|
|
case WM_WEBFOLDER_INIT:
|
|
if (!lParam)
|
|
return E_INVALIDARG;
|
|
pInfo = (CThreadArgs *) lParam;
|
|
if (!SetProp (hDlg, __INFO, (void *)lParam))
|
|
return E_FAIL;
|
|
pInfo->m_hwndMessage = hDlg;
|
|
break;
|
|
|
|
case WM_WEBFOLDER_CANCEL:
|
|
pInfo = (CThreadArgs *) GetProp (hDlg, __INFO);
|
|
if (!pInfo)
|
|
return E_FAIL;
|
|
if (!SetProp (hDlg, __CANCEL, STATUS_CANCELED))
|
|
return E_FAIL;
|
|
hwndDialog = pInfo->m_hwndDialog;
|
|
// let the navigateInternal call know that we are canceled.
|
|
pInfo->m_imsgStatus = READY_CANCEL;
|
|
if (hwndDialog)
|
|
SendMessage (hwndDialog, WM_WEBFOLDER_DONE, 0, 0);
|
|
return S_OK;
|
|
|
|
case WM_WEBFOLDER_NAV:
|
|
hCancel = GetProp (hDlg, __CANCEL);
|
|
if (!hCancel)
|
|
return E_FAIL;
|
|
if (hCancel != STATUS_CANCELED)
|
|
{
|
|
// we wait to get pInfo because if we canceled before, it
|
|
// doesn't exist anymore!
|
|
pInfo = (CThreadArgs *) GetProp (hDlg, __INFO);
|
|
if (!pInfo)
|
|
return E_FAIL;
|
|
|
|
pInfo->m_pidl = (LPITEMIDLIST) wParam;
|
|
pInfo->m_hrReady = (HRESULT)lParam;
|
|
hwndDialog = pInfo->m_hwndDialog;
|
|
pInfo->m_imsgStatus = READY_DONE;
|
|
if (hwndDialog)
|
|
SendMessage (hwndDialog, WM_WEBFOLDER_DONE, 0, 0);
|
|
}
|
|
DestroyWindow (hDlg);
|
|
return TRUE;
|
|
|
|
case WM_DESTROY:
|
|
RemoveProp (hDlg, __CANCEL);
|
|
RemoveProp (hDlg, __INFO);
|
|
break;
|
|
}
|
|
return DefWindowProc(hDlg, message, wParam, lParam);
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::ShowError
|
|
//
|
|
// Synopsis: Throws up a message box. The two unsinged ints point to
|
|
// entries in the string table. If the bstr is set, it will
|
|
// be placed in the %s location in the string table.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
void
|
|
Cwfolders::ShowError (HWND hwnd, unsigned int IDSmessage,
|
|
unsigned int IDStitle, BSTR bstrUrl)
|
|
{
|
|
WCHAR wszMessage [MAX_LOADSTRING+1];
|
|
WCHAR wszTitle [MAX_LOADSTRING+1];
|
|
|
|
LoadString(g_hInst, IDSmessage, wszMessage, ARRAYSIZE(wszMessage));
|
|
LoadString(g_hInst, IDStitle, wszTitle, ARRAYSIZE(wszTitle));
|
|
if (bstrUrl)
|
|
{
|
|
WCHAR * wsErrorMessage = new WCHAR [MAX_LOADSTRING+wcslen(bstrUrl)+1];
|
|
if (!wsErrorMessage)
|
|
{
|
|
ShowError (hwnd, IDS_ERROROUTOFMEMORY, IDS_ERROROUTOFMEMORYTITLE, NULL);
|
|
return;
|
|
}
|
|
wnsprintf (wsErrorMessage, MAX_LOADSTRING+wcslen(bstrUrl), wszMessage, bstrUrl);
|
|
MessageBox (hwnd, wsErrorMessage, wszTitle, MB_OK | MB_ICONERROR);
|
|
delete[] wsErrorMessage;
|
|
}
|
|
else
|
|
MessageBox (hwnd, wszMessage, wszTitle, MB_OK | MB_ICONERROR);
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::ShowNavigationFailed
|
|
//
|
|
// Synopsis: This guy gets called when there is no chance we can show
|
|
// the requested resource in ANY view. For instance, if the
|
|
// DNS lookup fails.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
void
|
|
Cwfolders::ShowNavigationFailed (HWND hWnd, BSTR bstrUrl, BSTR bstrTargetFrame,
|
|
WCHAR * wszResource)
|
|
{
|
|
VARIANT vTarget;
|
|
vTarget.vt = VT_BSTR;
|
|
|
|
// +1 for \0 and +1 for '#'
|
|
WCHAR * wszResUrl = new WCHAR [wcslen(bstrUrl) + wcslen(wszResource) + 2];
|
|
|
|
if (wszResUrl)
|
|
{
|
|
// This is how to hack a different URL into the address bar when
|
|
// showing an error page without having the address of the error
|
|
// page in there too.
|
|
wszResUrl [0] = NULL;
|
|
wcscat (wszResUrl, wszResource);
|
|
wcscat (wszResUrl, L"#");
|
|
wcscat (wszResUrl, bstrUrl);
|
|
|
|
vTarget.bstrVal = bstrTargetFrame;
|
|
m_pwb->Navigate (wszResUrl, NULL, &vTarget, NULL, NULL);
|
|
delete [] wszResUrl;
|
|
}
|
|
else
|
|
{
|
|
// the memory allocation failed. Oh well, so the url in
|
|
// the address bar is wrong.
|
|
vTarget.bstrVal = bstrTargetFrame;
|
|
m_pwb->Navigate (wszResource, NULL, &vTarget, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::CreateWebFolderIDList
|
|
//
|
|
// Synopsis: Asks office nse for a pidl, given an URL. This was written
|
|
// by Chris Guzak to be compatible with NT 5, which puts the
|
|
// office nse in a different place from NT 4, 9x.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
//Cwfolders::CreateWebFolderIDList(BSTR bstrUrl, LPITEMIDLIST *ppidl)
|
|
Cwfolders::CreateWebFolderIDList(BSTR bstrUrl, LPITEMIDLIST *ppidl, HWND hwnd, IUnknown* punk)
|
|
{
|
|
IShellFolder *psf = NULL;
|
|
HRESULT hr = SHGetDesktopFolder(&psf);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IBindCtx *pbc;
|
|
hr = CreateBindCtx(0, &pbc);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pbc->RegisterObjectParam((LPOLESTR)STR_PARSE_PREFER_FOLDER_BROWSING, punk);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ULONG ulAttr = SFGAO_FOLDER;
|
|
if (SUCCEEDED(hr = psf->ParseDisplayName(NULL, pbc, bstrUrl, NULL, ppidl, &ulAttr)))
|
|
{
|
|
if (!(ulAttr & SFGAO_FOLDER))
|
|
{
|
|
// fancy footwork to navigate to the parent folder if one exists
|
|
WCHAR * wszParentUrl = new WCHAR [1+SysStringLen(bstrUrl)];
|
|
if (wszParentUrl)
|
|
{
|
|
DWORD dwBuffSize = SysStringLen(bstrUrl);
|
|
// get name of parent folder
|
|
if (InternetCombineUrlW (bstrUrl, L"", wszParentUrl, &dwBuffSize, ICU_NO_ENCODE))
|
|
{
|
|
ulAttr = SFGAO_FOLDER;
|
|
hr = psf->ParseDisplayName(NULL, pbc, wszParentUrl, NULL, ppidl, &ulAttr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!(ulAttr & SFGAO_FOLDER))
|
|
hr = MK_E_NOSTORAGE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (GetLastError())
|
|
{
|
|
case ERROR_BAD_PATHNAME:
|
|
hr = MK_E_NOSTORAGE;
|
|
break;
|
|
case ERROR_INSUFFICIENT_BUFFER:
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
case ERROR_INTERNET_INVALID_URL:
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
default:
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
delete [] wszParentUrl;
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
}
|
|
pbc->Release();
|
|
}
|
|
psf->Release();
|
|
}
|
|
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
|
|
IShellFolder *psfb = NULL;
|
|
hr = SHGetDesktopFolder(&psf);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IBindCtx *pbc;
|
|
hr = CreateBindCtx(0, &pbc);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BIND_OPTS bo;
|
|
memset(&bo, 0, sizeof(bo));
|
|
bo.cbStruct = sizeof(bo);
|
|
bo.grfFlags = BIND_JUSTTESTEXISTENCE;
|
|
bo.grfMode = STGM_CREATE;
|
|
pbc->SetBindOptions(&bo);
|
|
|
|
// CLSID_MyComputer CLSID_WebFolders
|
|
WCHAR wszPath[] = L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{BDEADF00-C265-11D0-BCED-00A0C90AB50F}";
|
|
|
|
LPITEMIDLIST pidlo = NULL;
|
|
LPITEMIDLIST pidlurl = NULL;
|
|
ULONG chEaten = 0;
|
|
ULONG ulAttr = SFGAO_FOLDER;
|
|
|
|
// first PDN gets the Office shell folder pidl, then bind to it, next PDN tries for a pidl
|
|
// to our specific URL
|
|
if (SUCCEEDED(hr = psf->ParseDisplayName(NULL, pbc, wszPath, &chEaten, &pidlo, &ulAttr)) )
|
|
{
|
|
if( SUCCEEDED(hr = psf->BindToObject (pidlo, NULL, IID_IShellFolder, (void **) &psfb)) )
|
|
{
|
|
if( SUCCEEDED(hr = psfb->ParseDisplayName(hwnd, pbc, bstrUrl, &chEaten, &pidlurl, &ulAttr)))
|
|
{
|
|
if (!(ulAttr & SFGAO_FOLDER))
|
|
{
|
|
// fancy footwork to navigate to the parent folder if one exists
|
|
WCHAR * wszParentUrl = new WCHAR [1+SysStringLen(bstrUrl)];
|
|
if (wszParentUrl)
|
|
{
|
|
DWORD dwBuffSize = SysStringLen(bstrUrl);
|
|
// get name of parent folder
|
|
if (InternetCombineUrlW (bstrUrl, L"", wszParentUrl, &dwBuffSize, ICU_NO_ENCODE))
|
|
{
|
|
ulAttr = SFGAO_FOLDER;
|
|
hr = psfb->ParseDisplayName(NULL, pbc, wszParentUrl, &chEaten, &pidlurl, &ulAttr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!(ulAttr & SFGAO_FOLDER))
|
|
hr = MK_E_NOSTORAGE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (GetLastError())
|
|
{
|
|
case ERROR_BAD_PATHNAME:
|
|
hr = MK_E_NOSTORAGE;
|
|
break;
|
|
case ERROR_INSUFFICIENT_BUFFER:
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
case ERROR_INTERNET_INVALID_URL:
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
default:
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
delete [] wszParentUrl;
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (pidlurl && pidlo)
|
|
(*ppidl) = ILCombine (pidlo, pidlurl);
|
|
|
|
ILFree(pidlurl);
|
|
|
|
} // psfb->ParseDisplayName
|
|
|
|
} // psf->BindToObject
|
|
|
|
ILFree(pidlo);
|
|
} // psf->ParseDisplayName
|
|
|
|
pbc->Release();
|
|
|
|
} // CreateBindCtx
|
|
}
|
|
|
|
ReleaseInterface (psf);
|
|
ReleaseInterface (psfb);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
// ========================================================================
|
|
// The following three functions were taken from an SDK example.
|
|
// They are here to facilitate the packing of a PIDL into a
|
|
// VARIANT so that explorer will accept it for an argument to
|
|
// Navigate2.
|
|
// ========================================================================
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::InitVARIANTFromPidl
|
|
//
|
|
// Synopsis: Packs a pidl into a VARIANT
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
Cwfolders::InitVARIANTFromPidl(LPVARIANT pvar, LPITEMIDLIST pidl)
|
|
{
|
|
if (!pidl || !pvar)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
// Get the size of the pidl and allocate a SAFEARRAY of
|
|
// equivalent size
|
|
UINT cb = ILGetSize(pidl);
|
|
LPSAFEARRAY psa = MakeSafeArrayFromData((LPBYTE)pidl, cb);
|
|
if (!psa)
|
|
{
|
|
VariantInit(pvar);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
pvar->vt = VT_ARRAY|VT_UI1;
|
|
pvar->parray = psa;
|
|
return NOERROR;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::MakeSafeArrayFromData
|
|
//
|
|
// Synopsis: Allocates a SAFEARRAY of cbData size and packs pData into
|
|
// it.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
LPSAFEARRAY
|
|
Cwfolders::MakeSafeArrayFromData(LPBYTE pData, DWORD cbData)
|
|
{
|
|
LPSAFEARRAY psa;
|
|
|
|
if (!pData || 0 == cbData)
|
|
{
|
|
return NULL; // nothing to do
|
|
}
|
|
// create a one-dimensional safe array of BYTEs
|
|
psa = SafeArrayCreateVector(VT_UI1, 0, cbData);
|
|
if (psa)
|
|
{
|
|
// copy data into the area in safe array reserved for data
|
|
// Note we party directly on the pointer instead of using locking/
|
|
// unlocking functions. Since we just created this and no one
|
|
// else could possibly know about it or be using it, this is okay.
|
|
memcpy(psa->pvData,pData,cbData);
|
|
}
|
|
|
|
return psa;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: Cwfolders::ILGetSize
|
|
//
|
|
// Synopsis: Gets the size of the PIDL by walking the item id list
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
#define _ILSkip(pidl, cb) ((LPITEMIDLIST)(((BYTE*)(pidl))+cb))
|
|
#define _ILNext(pidl) _ILSkip(pidl, (pidl)->mkid.cb)
|
|
|
|
UINT
|
|
Cwfolders::ILGetSize(LPITEMIDLIST pidl)
|
|
{
|
|
UINT cbTotal = 0;
|
|
if (pidl)
|
|
{
|
|
cbTotal += sizeof(pidl->mkid.cb); // Null terminator
|
|
while (pidl->mkid.cb)
|
|
{
|
|
cbTotal += pidl->mkid.cb;
|
|
pidl = _ILNext(pidl);
|
|
}
|
|
}
|
|
return cbTotal;
|
|
}
|
|
|
|
// ========================================================================
|
|
// These two functions live in shdocvw. They are not, unfortunately,
|
|
// exported, so they appear here as well.
|
|
// ========================================================================
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// NAME: Cwfolders::ParseTargetType
|
|
//
|
|
// SYNOPSIS: Maps pszTarget into a target class.
|
|
//
|
|
// IMPLEMENTATION:
|
|
// Treats unknown MAGIC targets as _self
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
TARGET_TYPE
|
|
Cwfolders::ParseTargetType(LPCOLESTR pszTarget)
|
|
{
|
|
const TARGETENTRY *pEntry = targetTable;
|
|
|
|
if (pszTarget[0] != '_') return TARGET_FRAMENAME;
|
|
while (pEntry->pTargetValue)
|
|
{
|
|
if (!StrCmpW(pszTarget, pEntry->pTargetValue)) return pEntry->targetType;
|
|
pEntry++;
|
|
}
|
|
// Treat unknown MAGIC targets as regular frame name! <<for NETSCAPE compatibility>>
|
|
return TARGET_FRAMENAME;
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// NAME: Cwfolders::CreateTargetFrame
|
|
//
|
|
// SYNOPSIS: Creates a new window, if pszTargetName is not special
|
|
// target, names it pszTargetName. returns IUnknown for
|
|
// the object that implements ITargetFrame,IHlinkFrame and
|
|
// IWebBrowserApp.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
Cwfolders::CreateTargetFrame(LPCOLESTR pszTargetName, LPUNKNOWN /*IN,OUT*/ *ppunk)
|
|
{
|
|
LPTARGETFRAME2 ptgfWindowFrame;
|
|
HRESULT hr = S_OK;
|
|
|
|
// Launch a new window, set it's frame name to pszTargetName
|
|
// return it's IUnknown. If the new window is passed to us,
|
|
// just set the target name.
|
|
|
|
if (NULL == *ppunk)
|
|
{
|
|
#ifndef UNIX
|
|
hr = CoCreateInstance(CLSID_InternetExplorer, NULL,
|
|
CLSCTX_LOCAL_SERVER, IID_IUnknown, (LPVOID*)ppunk);
|
|
#else
|
|
hr = CoCreateInternetExplorer( IID_IUnknown,
|
|
CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER,
|
|
(LPVOID*) ppunk );
|
|
#endif
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Don't set frame name if target is special or missing
|
|
if (pszTargetName && ParseTargetType(pszTargetName) == TARGET_FRAMENAME)
|
|
{
|
|
HRESULT hrLocal;
|
|
hrLocal = (*ppunk)->QueryInterface(IID_ITargetFrame2, (LPVOID *)&ptgfWindowFrame);
|
|
if (SUCCEEDED(hrLocal))
|
|
{
|
|
ptgfWindowFrame->SetFrameName(pszTargetName);
|
|
ptgfWindowFrame->Release();
|
|
}
|
|
}
|
|
|
|
// Even if we don't set the frame name, we still want to return
|
|
// success, otherwise we'd have a blank window hanging around.
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// NAME: Cwfolders::SetScriptErrorMessage
|
|
//
|
|
// SYNOPSIS: This converts the hresult we would have returned from
|
|
// navigateInternal to a string to pass back to scripts
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
void
|
|
Cwfolders::SetScriptErrorMessage (HRESULT hr, BSTR * pbstr)
|
|
{
|
|
// These strings are what the scripting language recieves
|
|
// as our return value to navigate and navigateFrame
|
|
// The hr in the switch is the return value of NavigateInternal
|
|
switch (hr)
|
|
{
|
|
case S_OK:
|
|
*pbstr = SysAllocString (L"OK");
|
|
break;
|
|
case IPP_E_SERVERTYPE_NOT_SUPPORTED:
|
|
*pbstr = SysAllocString (L"PROTOCOL_NOT_SUPPORTED");
|
|
break;
|
|
case MK_E_NOOBJECT:
|
|
case DB_E_CANNOTCONNECT:
|
|
*pbstr = SysAllocString (L"LOCATION_DOES_NOT_EXIST");
|
|
break;
|
|
case DB_SEC_E_PERMISSIONDENIED:
|
|
*pbstr = SysAllocString (L"PERMISSION_DENIED");
|
|
break;
|
|
case E_INVALIDARG:
|
|
*pbstr = SysAllocString (L"INVALIDARG");
|
|
break;
|
|
case IPP_E_OFFLINE:
|
|
*pbstr = SysAllocString (L"OFFLINE");
|
|
break;
|
|
case E_OUTOFMEMORY:
|
|
*pbstr = SysAllocString (L"OUTOFMEMORY");
|
|
break;
|
|
case DB_E_TIMEOUT:
|
|
*pbstr = SysAllocString (L"TIMEOUT");
|
|
break;
|
|
case S_FALSE:
|
|
*pbstr = SysAllocString (L"CANCEL");
|
|
break;
|
|
case MK_E_CONNECTMANUALLY: //returned to us if we sent Office an ftp or file url
|
|
*pbstr = SysAllocString (L"PROTOCOL_NOT_SUPPORTED");
|
|
break;
|
|
default:
|
|
*pbstr = SysAllocString (L"FAILED");
|
|
break;
|
|
}
|
|
}
|