gecko-dev/cmd/winfe/ddecmd.cpp

413 lines
12 KiB
C++

/* -*- 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.
*/
//Created Abe Jarrett: Most of the methods in this class were taken from
//Garrett's code in dde.cpp. This file is intended only as
//a means of detecting seconds instance criteria and handling processing
//of it and any command line content as well.
#include "stdafx.h"
#include "ddecmd.h"
#include "ddectc.h"
// Our DDE instance identifier.
DWORD CDDECMDWrapper::m_dwidInst;
// Wether or not DDE was successfully initialized.
BOOL CDDECMDWrapper::m_bDDEActive;
// Our array of hsz strings.
HSZ CDDECMDWrapper::m_hsz[CDDECMDWrapper::m_MaxHSZ];
// A list of all current conversations. The PtrToPtr map was used since
// the pointers are known to be 32 bits long, and the HCONV is a
// DWORD or possibly a pointer, and WordToPtr just wouldn't cut it
// with 16 bits and all.
// Sounds good to me!
CMapPtrToPtr CDDECMDWrapper::m_ConvList;
// Command filter for DDEML
DWORD CDDECMDWrapper::m_dwafCmd;
// Call back function for use with DDEML
FARPROC CDDECMDWrapper::m_pfnCallBack;
//This kicks it all off.
void DDEInitCmdLineConversation()
{
CDDECMDWrapper::m_pfnCallBack = NULL;
#ifdef XP_WIN16
// Find out if we can even use DDEML (must be in protected mode).
// Undoubtedly, this is the case since we must be in protected
// mode to use WINSOCK services, but just to be anal....
// GetWinFlags() has been removed in MSVC 2.0 and the analog doesn't
// look like it does the same thing. chouck 29-Dec-94
if(!(GetWinFlags() & WF_PMODE)) {
// Not in protected mode, can not continue with DDEML
return ;
}
#endif
// Set up our callback function to be registered with DDEML.
CDDECMDWrapper::m_pfnCallBack = (FARPROC)CmdLineDdeCallBack;
if(DdeInitialize(&CDDECMDWrapper::m_dwidInst,
(PFNCALLBACK)CDDECMDWrapper::m_pfnCallBack,
CDDECMDWrapper::m_dwafCmd, 0L)) {
// Unable to initialize, don't continue.
return ;
}
CDDECMDWrapper::m_bDDEActive = TRUE;
// Load in all HSZs.
// Unfortunately, there is really no good way to detect any errors
// on these string intializations, so let the blame land
// where it will if something fails.
CString strCS;
strCS.LoadString(IDS_DDE_CMDLINE_SERVICE_NAME);
CDDECMDWrapper::m_hsz[CDDECMDWrapper::m_ServiceName] =
DdeCreateStringHandle(CDDECMDWrapper::m_dwidInst,
(char *)(const char *)strCS, CP_WINANSI);
strCS.LoadString(IDS_DDE_PROCESS_CMDLINE);
CDDECMDWrapper::m_hsz[CDDECMDWrapper::m_ProcessCmdLine] =
DdeCreateStringHandle(CDDECMDWrapper::m_dwidInst,
(char *)(const char *)strCS, CP_WINANSI);
}
// Purpose: Construct a DDECMDWrapper object
// Arguments: hszService The name of the service we are handling.
// hszTopic The name of the topic we are handling.
// hConv The handle of the conversation we are
// handling.
// Returns: nothing
// Comments: Handles all created objects internally through a map.
// Revision History:
//
CDDECMDWrapper::CDDECMDWrapper(HSZ hszService, HSZ hszTopic, HCONV hConv)
{
// Set our members passed in.
m_hszService = hszService;
m_hszTopic = hszTopic;
m_hConv = hConv;
// Figure out our enumerated service number.
// We know this anyhow, we only have one service name at this
// point.
m_iService = m_ServiceName;
// Figure out our enumerated topic number.
m_iTopic = EnumTopic(hszTopic);
// Add ourselves to the current map of conversations.
m_ConvList.SetAt((void *)hConv, this);
}
// Purpose: Destory a CDDECMDWrapper object
// Arguments: void
// Returns: nothing
// Comments: Removes us from the internally handled list
// Revision History:
//
CDDECMDWrapper::~CDDECMDWrapper()
{
// Remove ourselves from the list of current conversations.
m_ConvList.RemoveKey((void *)m_hConv);
}
// Purpose: Connect to a service using a specific topic
// Arguments: cpService The service name of the DDE server
// hszTopic The topic of the conversation to the server
// Returns: CDDECMDWrapper * The conversation object if established,
// otherwise NULL.
// Comments: Generic connection establishment.
// Revision History:
// 01-05-95 created GAB
CDDECMDWrapper *CDDECMDWrapper::ClientConnect(const char *cpService,
HSZ& hszTopic)
{
CDDECMDWrapper *pConv = NULL;
// Make the service name into an HSZ.
HSZ hszService = DdeCreateStringHandle(m_dwidInst,
(char *) cpService,
CP_WINANSI);
if(hszService == NULL) {
return(NULL);
}
// Establish the connection.
HCONV hConv = DdeConnect(m_dwidInst, hszService, hszTopic, NULL);
if(hConv != NULL) {
// We have a connection, all that's left to do is to create
// a CDDECMDWrapper, we'll be creating it with the wrong
// service name of course, but client connections no
// longer really care about the service connection number,
// all they need is the conversation handle.
pConv = new CDDECMDWrapper(m_hsz[m_ServiceName], hszTopic, hConv);
}
// Free off our created hsz.
DdeFreeStringHandle(m_dwidInst, hszService);
return(pConv);
}
// Purpose: Figure out which wrapper is associated with a conversation.
// Arguments: hConv The conversation to find out about.
// Returns: CDDECMDWrapper * A pointer to the CDDECMDWrapper that is
// handling the conversation, or NULL
// if none is present.
// Comments: Shouldn't ever return NULL really.
// Revision History:
// 12-30-94 created GAB
// 12-04-96 reused by AJ. Probably not necessary, but you never know
// know when we may have to do more than one conversation.
CDDECMDWrapper *CDDECMDWrapper::GetConvObj(HCONV hConv)
{
// Query our static map of conversations for the object.
void *pWrap;
if(m_ConvList.Lookup((void *)hConv, pWrap) == 0) {
return(NULL);
}
return((CDDECMDWrapper *)pWrap);
}
// Purpose: Return the offset of the hsz topic string in our static
// m_hsz array
// Arguments: hsz The HSZ string to find in our array
// Returns: int The offset into the array, also correlating to
// it's enumerated value. If not found, the
// returned failure value is 0.
// Comments: Mainly coded to remove redundant lookups. Modularity...
// Revision History:
// 12-30-94 created GAB
// 12-04-96 reused by AJ. Probably not necessary, but you never know
// know when we may have to handle more than one topic.
int CDDECMDWrapper::EnumTopic(HSZ& hsz)
{
int i_retval = 0;
int i_counter;
// Just start looking for the HSZ string in our static array.
for(i_counter = m_TopicStart; i_counter < m_MaxHSZ; i_counter++)
{
if(m_hsz[i_counter] == hsz) {
i_retval = i_counter;
break;
}
}
return(i_retval);
}
HDDEDATA
CALLBACK
#ifndef XP_WIN32
_export
#endif
CmdLineDdeCallBack(UINT type, UINT fmt,
HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1,
DWORD dwData2)
{
// Depending on the class of transaction, we return different data.
if(type & XCLASS_BOOL) {
// Must return (HDDEDATA)TRUE or (HDDEDATA)FALSE
switch(type) {
case XTYP_CONNECT: {
// We are the server.
// A client call the DdeConnect specifying a service and
// topic name which we support.
HSZ& hszTopic = hsz1;
HSZ& hszService = hsz2;
// Deny the connection if the service name is not the
// one we are taking connections for.
if(hszService !=
CDDECMDWrapper::m_hsz[CDDECMDWrapper::m_ServiceName]) {
return((HDDEDATA)FALSE);
}
// Now, the topic can be NULL, or it can be any one of our
// topic names to be accepted.
if(hszTopic == NULL) {
return((HDDEDATA)TRUE);
}
// Go through all our topics, see if we match.
if(0 != CDDECMDWrapper::EnumTopic(hszTopic)) {
return((HDDEDATA)TRUE);
}
// Topic not supported
return((HDDEDATA)FALSE);
}
default:
// unknown
return((HDDEDATA)FALSE);
}
// Break handled here
return((HDDEDATA)FALSE);
}
else if(type & XCLASS_DATA) {
// Must return DDE data handle, CBR_BLOCK, or NULL
return(NULL);
}
else if(type & XCLASS_FLAGS) {
// Must return DDE_FACK, DDE_BUSY, or DDE_FNOTPROCESSED
switch(type) {
case XTYP_ADVDATA: {
// We are the client.
// The server gave us a data handle.
break;
}
case XTYP_EXECUTE: {
// We are the server.
// A client said XTYP_EXECUTE in DdeClientTransaction
// If we are currently not fully initialized, we must ignore
// the request, but acknowledge it nonetheless.
if(theApp.m_bInInitInstance) {
return (HDDEDATA)DDE_FACK;
}
HDDEDATA& hDataExecute = hData;
char *pData = (char *)DdeAccessData(hDataExecute, NULL);
char szCmd[_MAX_PATH+12];
strcpy ( szCmd, "[cmdline(\"" );
strcat ( szCmd, pData );
strcat ( szCmd, "\")]" );
BOOL bRetval = theApp.OnDDECommand(szCmd);
DdeUnaccessData(hDataExecute);
return((HDDEDATA) bRetval);
}
default:
// unknown
return(DDE_FNOTPROCESSED);
}
// Break handled here
return(DDE_FNOTPROCESSED);
}
else if(type & XCLASS_NOTIFICATION) {
// Must return NULL, as the return value is ignored
switch(type) {
case XTYP_ADVSTOP: {
// We are the server
// A client said XTYP_ADVSTOP in DdeClientTransaction
break;
}
case XTYP_CONNECT_CONFIRM: {
// We are the server.
// We returned 1 to a XTYP_CONNECT transaction.
// This callback is mainly to inform us of the conversation
// handle that now exists, but we will actually be
// creating an instance of an object to handle this
// conversation from now on.
HSZ& hszTopic = hsz1;
HSZ& hszService = hsz2;
// Create the object, correctly initialized so that
// it understands the service, topic, and conversation
// it is handling.
// It will add itself to the conversation list.
CDDECMDWrapper *pObject = new CDDECMDWrapper(hszService, hszTopic,
hconv);
break;
}
case XTYP_DISCONNECT: {
// We are either client/server
// The partner in the conversation called DdeDisconnect
// causing both client/server to receive this.
// Find out which conversation object we are dealing with.
CDDECMDWrapper *pWrapper = CDDECMDWrapper::GetConvObj(hconv);
// Simply delete it.
// The object takes care of removing itself from the list.
if(pWrapper != NULL) {
delete pWrapper;
}
break;
}
case XTYP_ERROR: {
// We are either client/server
// A serious error has occurred.
// DDEML doesn't have any resources left to guarantee
// good communication.
break;
}
case XTYP_REGISTER: {
// We are either client/server
// A server application used DdeNameService to register
// a new service name.
break;
}
case XTYP_UNREGISTER: {
// We are either client/server
// A server applciation used DdeNameService to unregister
// an old service name.
break;
}
case XTYP_XACT_COMPLETE: {
// We are the client
// An asynchronous tranaction, sent when the client specified
// the TIMEOUT_ASYNC flag in DdeClientTransaction has
// concluded.
break;
}
default:
// unknown
return(NULL);
}
return(NULL);
}
// Unknown class type
return(NULL);
}