mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 08:12:05 +00:00
268 lines
9.7 KiB
C++
Executable File
268 lines
9.7 KiB
C++
Executable File
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "olectc.h"
|
|
|
|
#include "presentm.h"
|
|
#include "oleview1.h"
|
|
#include "cxsave.h"
|
|
#include "winproto.h"
|
|
|
|
extern "C" int MK_OUT_OF_MEMORY; // defined in allxpstr.h
|
|
|
|
|
|
COLEStreamData::COLEStreamData(const char *pServer, const char *pMimeType) : CStreamData(CStreamData::m_OLE) {
|
|
// Purpose: Construct the data stream object.
|
|
// Arguments: pServer The registry name of the automation server that we should contact in our data stream.
|
|
// pMimeType The Mime type of the stream.
|
|
// Returns: none
|
|
// Comments: Note that we initialize the base class to know that we are an OLE viewer.
|
|
|
|
// Just copy over the relevant members.
|
|
m_csServerName = pServer;
|
|
m_csMimeType = pMimeType;
|
|
}
|
|
|
|
COLEDownloadData::COLEDownloadData(COLEStreamData *pCData, const char *pAddress) {
|
|
// Purpose: Create an instance of the download data.
|
|
// Arguments: pCData A global object representing the OLE registered server.
|
|
// pAddress The URL that we are about to handle.
|
|
// Returns: none
|
|
// Comments: Download instance specific member.
|
|
|
|
// Assign over our data.
|
|
m_pCData = pCData;
|
|
m_pBuffer = NULL;
|
|
m_bReadyCalled = FALSE;
|
|
|
|
// Attach ourselves to the OLE Automation server.
|
|
// If an exception is thrown, it's handled elsewhere.
|
|
TRACE("%s:Initialize(%s, %s)\n", (const char *)m_pCData->m_csServerName, (const char *)m_pCData->m_csMimeType, pAddress);
|
|
m_Viewer.CreateDispatch(m_pCData->m_csServerName);
|
|
if(0 == m_Viewer.Initialize(m_pCData->m_csMimeType, pAddress)) {
|
|
AfxThrowNotSupportedException();
|
|
}
|
|
|
|
// Attempt to allocate a small buffer to start out with.
|
|
// This may grow later, we don't really care.
|
|
if(NULL == (m_pBuffer = SysAllocStringLen(NULL, m_InitialBufferSize))) {
|
|
AfxThrowMemoryException();
|
|
}
|
|
}
|
|
|
|
COLEDownloadData::~COLEDownloadData() {
|
|
// Use to free off our buffer if it exists.
|
|
if(m_pBuffer != NULL) {
|
|
SysFreeString(m_pBuffer);
|
|
}
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
NET_StreamClass *ole_stream(int iFormatOut, void *vpDataObj, URL_Struct *pURL, MWContext *pContext) {
|
|
// Purpose: Return the stream class for our OLE automated stream.
|
|
// Arguments: iFormatOut The representation we are outputting (should be FO_PRESENT only for now)
|
|
// vpDataObj Our COLEStreamData structure.
|
|
// pURL The URL we're loading.
|
|
// pContext The current context that we're loading in.
|
|
// Returns: NET_StreamClass A group of functions that will handle the intimate details
|
|
// of the download.
|
|
// Comments: Set up the data stream.
|
|
// Initiate the conversation with the automation server.
|
|
// The stream will be lost if unable to establish the connection. Can't really handle well.
|
|
|
|
// Convert our data object.
|
|
COLEStreamData *pCData = (COLEStreamData *)vpDataObj;
|
|
COLEDownloadData *pOData = NULL;
|
|
// Create the stream data.
|
|
TRY {
|
|
pOData = new COLEDownloadData(pCData, pURL->address);
|
|
|
|
NET_StreamClass *pOleStream = NET_NewStream("Speghetti(SP)",
|
|
ole_StreamWrite,
|
|
ole_StreamComplete,
|
|
ole_StreamAbort,
|
|
ole_StreamReady,
|
|
(void *)pOData,
|
|
pContext);
|
|
|
|
// See if we can't get this to load in a seperate context.
|
|
// It will correctly call the stream members, and also reset
|
|
// the context if able.
|
|
NET_StreamClass *pRetval =
|
|
CSaveCX::OleStreamObject(pOleStream, pURL, pCData->m_csServerName);
|
|
if(pRetval == NULL) {
|
|
// Couldn't switch
|
|
pRetval = pOleStream;
|
|
}
|
|
|
|
return(pRetval);
|
|
}
|
|
CATCH(CException, e) { // Any exception will do
|
|
|
|
// Tell the user that we were unable to complete the operation, ask them if they would like to unregister the OLE viewer.
|
|
TRACE("Couldn't connect to the OLE automation server\n");
|
|
CString csMessage = szLoadString(IDS_OLE_CANTUSE_VIEWER);
|
|
csMessage += pCData->m_csServerName;
|
|
csMessage += szLoadString(IDS_OLE_CANTUSE_VIEWER2);
|
|
|
|
if(IDNO == AfxMessageBox(csMessage, MB_YESNO)) {
|
|
// They don't want to use the viewer in the future.
|
|
// Unregister it; assume FO_PRESENT.
|
|
WPM_UnRegisterContentTypeConverter(pCData->m_csServerName, pCData->m_csMimeType, FO_PRESENT);
|
|
|
|
// Remove the registration from the INI file also.
|
|
theApp.WriteProfileString("Automation Viewers", pCData->m_csMimeType, NULL);
|
|
|
|
// We know it's registered, and we know it's our current data, so remove it.
|
|
delete(pCData);
|
|
}
|
|
if(pOData != NULL) {
|
|
delete(pOData);
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
END_CATCH
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
int ole_StreamWrite(NET_StreamClass *stream, const char *cpWriteData, int32 lLength) {
|
|
// Purpose: Write data to our automated object.
|
|
// Arguments: vpDataObject The COLEDownloadObject for the load.
|
|
// cpWriteData The data to write.
|
|
// lLength The length of the string we're writing.
|
|
// Returns: int MK_DATA_LOADED always.
|
|
// Comments: Used to write data to the streaming viewer.
|
|
// If the viewer doesn't want the data, it should report the error status in Ready.
|
|
|
|
void *vpDataObj=stream->data_object;
|
|
// Obtain the object.
|
|
COLEDownloadData *pOData = (COLEDownloadData *)vpDataObj;
|
|
|
|
// Check to see if the netlib didn't check is_write_ready
|
|
if(pOData->m_bReadyCalled == FALSE) {
|
|
TRACE("Please call Ready first. This is a serious hack.\n");
|
|
|
|
// Since the netlib is being harsh to us, we have to do some special handling here.
|
|
// We're going to do a tight loop, until the other viewer has gotten all the data
|
|
// that we just got handed, and then we'll return as normal.
|
|
// Enough OLE messages will be generated to keep the application running....
|
|
long lReady = 0;
|
|
long lOffset = 0;
|
|
while(1) {
|
|
lReady = ole_StreamReady(stream);
|
|
if(lReady == 0) {
|
|
continue;
|
|
}
|
|
else if(lReady < 0) {
|
|
// Hm, they said error.
|
|
pOData->m_bReadyCalled = FALSE;
|
|
return(CASTINT(lReady));
|
|
}
|
|
|
|
// Okay, see if the ready amount is the amount we can send.
|
|
if(lReady + lOffset >= lLength) {
|
|
lReady = lLength - lOffset;
|
|
if(lReady == 0) {
|
|
pOData->m_bReadyCalled = FALSE;
|
|
return(MK_DATA_LOADED);
|
|
}
|
|
}
|
|
|
|
// Send the data.
|
|
ole_StreamWrite(stream, cpWriteData + lOffset, lReady);
|
|
|
|
// Increment our offset into the buffer.
|
|
lOffset += lReady;
|
|
}
|
|
}
|
|
|
|
// Clear this out for next time.
|
|
pOData->m_bReadyCalled = FALSE;
|
|
|
|
// If the length is greater than our buffer, then it's time to resize.
|
|
if((int32)SysStringLen(pOData->m_pBuffer) < lLength) {
|
|
if(FALSE == SysReAllocStringLen(&(pOData->m_pBuffer), NULL, CASTUINT(lLength))) {
|
|
// Couldn't do it, return an error.
|
|
return(MK_OUT_OF_MEMORY);
|
|
}
|
|
}
|
|
|
|
// Copy over the bytes.
|
|
memcpy(pOData->m_pBuffer, cpWriteData, CASTSIZE_T(lLength));
|
|
|
|
// Write it to the viewer.
|
|
pOData->m_Viewer.Write(&(pOData->m_pBuffer), lLength);
|
|
return(MK_DATA_LOADED);
|
|
}
|
|
|
|
void ole_StreamComplete(NET_StreamClass *stream) {
|
|
// Purpose: Normally complete the stream.
|
|
// Arguments: vpDataObj The COLEDownloadData object, which we will simply destroy.
|
|
// Returns: void
|
|
// Comments: Return a normal status to the viewer.
|
|
|
|
// Obtain our download data.
|
|
COLEDownloadData *pOData = (COLEDownloadData *)stream->data_object;
|
|
|
|
// Close, with no error.
|
|
pOData->m_Viewer.Close(0);
|
|
|
|
// Delete the object.
|
|
delete(pOData);
|
|
}
|
|
|
|
void ole_StreamAbort(NET_StreamClass *stream, int iStatus) {
|
|
// Purpose: Abort the stream for miscellaneous reasons.
|
|
// Arguments: vpDataObj The COLEDownloadData object, we'll destroy this.
|
|
// iStatus The error status, which we pay no attention to.
|
|
// Returns: void
|
|
// Comments: Return an error status to the viewer.
|
|
|
|
// Obtain our download data.
|
|
COLEDownloadData *pOData = (COLEDownloadData *)stream->data_object;
|
|
|
|
// Close, with error.
|
|
pOData->m_Viewer.Close(-1);
|
|
|
|
// Delete the object.
|
|
delete(pOData);
|
|
}
|
|
|
|
unsigned int ole_StreamReady(NET_StreamClass *stream) {
|
|
// Purpose: Return the number of bytes which we are ready to have written to us.
|
|
// Arguments: vpDataObj The COLEDownloadData which handles the download.
|
|
// Returns: unsigned int The number of bytes that we're ready for.
|
|
// Comments: We really simply ask the viewer how much they're ready to handle.
|
|
|
|
// Obtain our download data.
|
|
COLEDownloadData *pOData = (COLEDownloadData *)stream->data_object;
|
|
|
|
// Mark that the netlib actually called us.
|
|
pOData->m_bReadyCalled = TRUE;
|
|
|
|
// Return the amount that the viewer reports.
|
|
return(CASTUINT(pOData->m_Viewer.Ready()));
|
|
}
|
|
|
|
};
|