| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***************************************************************************
- ** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
- ***************************************************************************
- * *
- * Project Name : Dynamic Data Encapsulation *
- * *
- * File Name : DDE.CPP *
- * *
- * Programmer : Steve Wetherill *
- * *
- * Start Date : June 1, 1996 *
- * *
- * Last Update : June 8, 1996 [SW] *
- * *
- *-------------------------------------------------------------------------*
- * Functions: *
- * Instance_Class::InstanceClass -- class constructor *
- * Instance_Class::InstanceClass -- class destructor *
- * Instance_Class::Enable_Callback -- enables local processing of pokes *
- * Instance_Class::Register_Servers -- registers a local DDE DNS service *
- * Instance_Class::Cleanup_App -- currently does nothing *
- * Instance_Class::Test_Server_Running -- does a trial connect to remote *
- * Instance_Class::Open_Poke_Connection -- pokes some data to server *
- * Instance_Class::Close_Poke_Connectionp -- closes connection to remote *
- * Instance_Class::Poke_Server -- sends a chunk of data to remote *
- * Instance_Class::dde_callback -- processes DDE transactions *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #ifdef WIN32
- #include <windows.h>
- #include "dde.h"
- /***************************************************************************
- * These are static members of Instance_Class
- *=========================================================================*/
- static DWORD Instance_Class::id_inst; // instance identifier set by DdeInitialize
- static BOOL Instance_Class::process_pokes; // controls response to pokes
- static char Instance_Class::ascii_name[32]; // name of server
- static BOOL CALLBACK (*Instance_Class::callback) (
- LPBYTE pointer, // pointer to received data
- long length // length of received data or advisory flag
- ) = NULL;
- /***************************************************************************
- * Instance_Class::InstanceClass -- class constructor *
- * *
- * INPUT: *
- * name1 null terminated ASCII client name *
- * name1 null terminated ASCII server name *
- * *
- * OUTPUT: *
- * dde_error = TRUE if error occurs when initializing DDE *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- Instance_Class::Instance_Class( LPSTR name1, LPSTR name2 )
- {
- dde_error = FALSE; // no errors
- process_pokes = FALSE; // disable pokes in callback
- id_inst = 0; // set to 0 for first time through
- conv_handle = 0; // conversation handle reset
- lstrcpy( ascii_name, name1 ); // keep a record of ASCII name
- if ( DdeInitialize(
- (LPDWORD) &id_inst, // instance identifier
- dde_callback,
- APPCLASS_STANDARD | // filter server messages
- CBF_FAIL_SELFCONNECTIONS, // prevent from connecting with self
- 0) != DMLERR_NO_ERROR) { // reserved
- dde_error = TRUE; // flag an error
- }
- local_name = DdeCreateStringHandle(
- id_inst, // instance identifier
- name1, // string to register
- CP_WINANSI); // Windows ANSI code page
- remote_name = DdeCreateStringHandle(
- id_inst, // instance identifier
- name2, // string to register
- CP_WINANSI); // Windows ANSI code page
- poke_topic = DdeCreateStringHandle(
- id_inst, // instance identifier
- "POKE TOPIC", // System topic
- CP_WINANSI); // Windows ANSI code page
- poke_item = DdeCreateStringHandle(
- id_inst, // instance identifier
- "POKE ITEM", // System topic
- CP_WINANSI); // Windows ANSI code page
- system_topic = DdeCreateStringHandle(
- id_inst, // instance identifier
- SZDDESYS_TOPIC, // System topic
- CP_WINANSI); // Windows ANSI code page
- }
- /***************************************************************************
- * Instance_Class::~Instance_Class -- class destructor *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- Instance_Class::~Instance_Class()
- {
- DdeUninitialize( id_inst );
- }
- /***************************************************************************
- * Instance_Class::Enable_Callback -- enables user callback *
- * *
- * INPUT: *
- * TRUE = enable poke processing *
- * FALSE = disable poke processing *
- * *
- * OUTPUT: *
- * echos the input *
- * *
- * WARNINGS: *
- * user callback must be explicitly enabled. Disbabled by default. *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- BOOL Instance_Class::Enable_Callback( BOOL flag ) // enable or disable callback
- {
- return (process_pokes = flag);
- }
- /***************************************************************************
- * Instance_Class::Register_Server -- registers a local DDE DNS service *
- * *
- * INPUT: *
- * BOOL CALLBACK ( *callback_fnc) ( LPBYTE, DWORD) = user poke callbacl *
- * *
- * OUTPUT: *
- * TRUE == success *
- * FALSE == failed *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- BOOL Instance_Class::Register_Server( BOOL CALLBACK ( *callback_fnc) (LPBYTE, long) )
- {
- if (DdeNameService( id_inst, local_name, 0L, DNS_REGISTER ) != 0L) {
- callback = callback_fnc;
- return ( TRUE );
- } else {
- return ( FALSE );
- }
- }
- /***************************************************************************
- * Instance_Class::Test_Server_Running -- does a trial connect to remote *
- * *
- * INPUT: *
- * name = HSZ string handle of server name. *
- * *
- * OUTPUT: *
- * TRUE == successfully connected to remote *
- * FALSE == failed to connect *
- * *
- * WARNINGS: *
- * - Can be called for local or remote server but of course will *
- * fail if a called for local and local server is not "up". *
- * - Disconects before exiting. *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- BOOL Instance_Class::Test_Server_Running( HSZ name )
- {
- if( Open_Poke_Connection( name ) == TRUE) {
- Close_Poke_Connection();
- return( TRUE );
- } else {
- return( FALSE );
- }
- }
- /***************************************************************************
- * Instance_Class::Open_Poke_Connection -- open a connection to server *
- * *
- * INPUT: *
- * name = HSZ server name. *
- * *
- * OUTPUT: *
- * TRUE == successfully opened connection *
- * FALSE == failed to connect *
- * *
- * WARNINGS: *
- * Can be called for local or remote server but of course will *
- * fail if a called for local and local server is not "up". *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- BOOL Instance_Class::Open_Poke_Connection( HSZ name )
- {
- conv_handle = DdeConnect(
- id_inst, // instance identifier
- name, // service name string handle
- poke_topic, // topic string handle
- (PCONVCONTEXT) NULL);// use default context
- if (conv_handle == NULL) {
- return FALSE;
- } else {
- return TRUE;
- }
- }
- /***************************************************************************
- * Instance_Class::Close_Poke_Connection -- closes poke connection *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * TRUE == successfully closed connection *
- * FALSE == failed to close connection for some reason *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- BOOL Instance_Class::Close_Poke_Connection( void )
- {
- if( conv_handle ) {
- HCONV temp_handle = conv_handle;
- conv_handle = NULL;
- return( DdeDisconnect( temp_handle ));
- } else {
- return( TRUE );
- }
- }
- /***************************************************************************
- * Instance_Class::Poke_Server -- pokes some data to server *
- * *
- * INPUT: *
- * poke_data points to data to send to remote *
- * poke_length length of buffer to send *
- * *
- * OUTPUT: *
- * TRUE == successfully poked the data *
- * FALSE == failed to connect *
- * *
- * WARNINGS: *
- * has a 3 second timeout (change POKE_TIMEOUT, in milliseconds) *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- #define POKE_TIMEOUT 60*1000 // 60 sec timeout
- BOOL Instance_Class::Poke_Server( LPBYTE poke_data, DWORD poke_length )
- {
- if( DdeClientTransaction(
- poke_data, // address of data to pass to server
- poke_length, // length of data
- conv_handle, // handle of conversation
- poke_topic, // handle of item name string
- CF_TEXT, // no special clipboard data format
- XTYP_POKE, // transaction type
- POKE_TIMEOUT, // time-out duration (millisecs)
- (LPDWORD) NULL // address of transaction result (don't check)
- ) == 0) {
- return( FALSE);
- } else {
- return( TRUE );
- }
- }
- /***************************************************************************
- * Instance_Class::dde_callback -- callback dde event handler *
- * *
- * INPUT: *
- * dde_event transaction type *
- * uFmt clipboard data format *
- * hconv handle of the conversation *
- * hsz1 handle of a string *
- * hsz2 handle of a string *
- * hdata handle of a global memory object *
- * dwData1 transaction-specific data *
- * dwData2 transaction-specific data *
- * *
- * OUTPUT: *
- * context specific HDDEDATA object *
- * *
- * WARNINGS: *
- * NOTE: declared as HDDEDATA CALLBACK which means PASCAL parameters *
- * *
- * HISTORY: *
- * 6/1/1996 SW : Created. *
- *=========================================================================*/
- HDDEDATA CALLBACK Instance_Class::dde_callback(
- UINT dde_event, // transaction type
- UINT uFmt, // clipboard data format
- HCONV , // handle of the conversation
- HSZ hsz1, // handle of a string
- HSZ hsz2, // handle of a string
- HDDEDATA hdata, // handle of a global memory object
- DWORD , // transaction-specific data
- DWORD // transaction-specific data
- )
- {
- if (!Instance_Class::callback){
- return (HDDEDATA) NULL;
- }
- switch ( dde_event ) {
- case XTYP_REGISTER:
- case XTYP_UNREGISTER:
- return (HDDEDATA) NULL;
- case XTYP_ADVDATA:
- return (HDDEDATA) DDE_FACK;
- case XTYP_XACT_COMPLETE:
- return (HDDEDATA) NULL;
- case XTYP_DISCONNECT:
- Instance_Class::callback( NULL, DDE_ADVISE_DISCONNECT);
- return (HDDEDATA) NULL;
- case XTYP_CONNECT: {
- char buffer[32];
- DdeQueryString (Instance_Class::id_inst, hsz2, buffer, sizeof (buffer), 0) ;
- if (0 != strcmp (buffer, Instance_Class::ascii_name)) {
- return (HDDEDATA) NULL;
- }
- DdeQueryString (Instance_Class::id_inst, hsz1, buffer, sizeof (buffer), 0) ;
- if (0 != strcmp (buffer, "POKE TOPIC")) {
- return (HDDEDATA) NULL;
- }
- Instance_Class::callback( NULL, DDE_ADVISE_CONNECT);
- return (HDDEDATA) TRUE;
- }
- case XTYP_POKE:
- if (Instance_Class::process_pokes == FALSE ) {
- return (HDDEDATA) DDE_FNOTPROCESSED; // processing disabled
- } else {
- char buffer[32];
- DdeQueryString (Instance_Class::id_inst, hsz1, buffer, sizeof (buffer), 0) ;
- if (0 != strcmp (buffer, "POKE TOPIC")) {
- return (HDDEDATA) DDE_FNOTPROCESSED;
- } else if (uFmt == CF_TEXT) { // make sure it's CF_TEXT
- BOOL processed;
- BYTE FAR *pdata;
- DWORD dw_length;
- if ( (pdata = DdeAccessData( hdata, &dw_length)) == NULL ) {
- return (HDDEDATA) DDE_FNOTPROCESSED;
- }
- processed = Instance_Class::callback((LPBYTE) pdata, dw_length);
- DdeUnaccessData( hdata );
- if (processed == TRUE) {
- return (HDDEDATA) DDE_FACK;
- } else {
- return (HDDEDATA) NULL;
- }
- }
- }
- default:
- return (HDDEDATA) NULL;
- }
- }
- #endif //WIN32
|