home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / ddecmd.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  11.7 KB  |  406 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. //Created Abe Jarrett:  Most of the methods in this class were taken from
  20. //Garrett's code in dde.cpp.  This file is intended only as
  21. //a means of detecting seconds instance criteria and handling processing
  22. //of it and  any command line content as well.
  23.  
  24. #include "stdafx.h"
  25.  
  26. #include "ddecmd.h"
  27. #include "ddectc.h"
  28.  
  29.  
  30. //    Our DDE instance identifier.
  31. DWORD CDDECMDWrapper::m_dwidInst;
  32.  
  33. //    Wether or not DDE was successfully initialized.
  34. BOOL CDDECMDWrapper::m_bDDEActive;
  35.  
  36. //    Our array of hsz strings.
  37. HSZ CDDECMDWrapper::m_hsz[CDDECMDWrapper::m_MaxHSZ];
  38.  
  39. //    A list of all current conversations.  The PtrToPtr map was used since
  40. //        the pointers are known to be 32 bits long, and the HCONV is a 
  41. //        DWORD or possibly a pointer, and WordToPtr just wouldn't cut it
  42. //        with 16 bits and all.  
  43. //    Sounds good to me!
  44. CMapPtrToPtr CDDECMDWrapper::m_ConvList;
  45.  
  46. //    Command filter for DDEML
  47. DWORD CDDECMDWrapper::m_dwafCmd;
  48.  
  49. //    Call back function for use with DDEML
  50. FARPROC CDDECMDWrapper::m_pfnCallBack;
  51.  
  52.  
  53. //This kicks it all off.
  54. void DDEInitCmdLineConversation()
  55. {
  56.  
  57.     CDDECMDWrapper::m_pfnCallBack = NULL;
  58.  
  59. #ifdef XP_WIN16
  60.     //    Find out if we can even use DDEML (must be in protected mode).
  61.     //    Undoubtedly, this is the case since we must be in protected
  62.     //        mode to use WINSOCK services, but just to be anal....
  63.     //  GetWinFlags() has been removed in MSVC 2.0 and the analog doesn't
  64.     //      look like it does the same thing.  chouck 29-Dec-94
  65.     if(!(GetWinFlags() & WF_PMODE))    {
  66.         //    Not in protected mode, can not continue with DDEML
  67.         return ;
  68.     }
  69. #endif
  70.     
  71.     //    Set up our callback function to be registered with DDEML.
  72.     CDDECMDWrapper::m_pfnCallBack = (FARPROC)CmdLineDdeCallBack;
  73.  
  74.             
  75.     if(DdeInitialize(&CDDECMDWrapper::m_dwidInst,
  76.         (PFNCALLBACK)CDDECMDWrapper::m_pfnCallBack,
  77.         CDDECMDWrapper::m_dwafCmd, 0L))    {
  78.         //    Unable to initialize, don't continue.
  79.         return ; 
  80.     }
  81.  
  82.  
  83.     CDDECMDWrapper::m_bDDEActive = TRUE;
  84.     
  85.     //    Load in all HSZs.
  86.     //    Unfortunately, there is really no good way to detect any errors
  87.     //        on these string intializations, so let the blame land
  88.     //        where it will if something fails.
  89.     CString strCS;
  90.     
  91.     strCS.LoadString(IDS_DDE_CMDLINE_SERVICE_NAME);
  92.     CDDECMDWrapper::m_hsz[CDDECMDWrapper::m_ServiceName] =
  93.         DdeCreateStringHandle(CDDECMDWrapper::m_dwidInst,
  94.         (char *)(const char *)strCS, CP_WINANSI);
  95.  
  96.     strCS.LoadString(IDS_DDE_PROCESS_CMDLINE);
  97.     CDDECMDWrapper::m_hsz[CDDECMDWrapper::m_ProcessCmdLine] =
  98.         DdeCreateStringHandle(CDDECMDWrapper::m_dwidInst,
  99.         (char *)(const char *)strCS, CP_WINANSI);
  100.     
  101. }
  102.  
  103.  
  104. //    Purpose:    Construct a DDECMDWrapper object
  105. //    Arguments:    hszService    The name of the service we are handling.
  106. //                hszTopic    The name of the topic we are handling.
  107. //                hConv        The handle of the conversation we are
  108. //                                handling.
  109. //    Returns:    nothing
  110. //    Comments:    Handles all created objects internally through a map.
  111. //    Revision History:
  112. //
  113. CDDECMDWrapper::CDDECMDWrapper(HSZ hszService, HSZ hszTopic, HCONV hConv)
  114. {
  115.     //    Set our members passed in.
  116.     m_hszService = hszService;
  117.     m_hszTopic = hszTopic;
  118.     m_hConv = hConv;
  119.     
  120.     //    Figure out our enumerated service number.
  121.     //    We know this anyhow, we only have one service name at this
  122.     //        point.
  123.     m_iService = m_ServiceName;
  124.     
  125.     //    Figure out our enumerated topic number.
  126.     m_iTopic = EnumTopic(hszTopic);
  127.     
  128.     //    Add ourselves to the current map of conversations.
  129.     m_ConvList.SetAt((void *)hConv, this);
  130. }
  131.  
  132.  
  133. //    Purpose:    Destory a CDDECMDWrapper object
  134. //    Arguments:    void
  135. //    Returns:    nothing
  136. //    Comments:    Removes us from the internally handled list
  137. //    Revision History:
  138. //    
  139.  
  140. CDDECMDWrapper::~CDDECMDWrapper()
  141. {
  142.     //    Remove ourselves from the list of current conversations.
  143.     m_ConvList.RemoveKey((void *)m_hConv);
  144. }
  145.  
  146.  
  147.  
  148. //    Purpose:    Connect to a service using a specific topic
  149. //    Arguments:    cpService    The service name of the DDE server
  150. //                hszTopic    The topic of the conversation to the server
  151. //    Returns:    CDDECMDWrapper *    The conversation object if established,
  152. //                                    otherwise NULL.
  153. //    Comments:    Generic connection establishment.
  154. //    Revision History:
  155. //        01-05-95    created GAB
  156. CDDECMDWrapper *CDDECMDWrapper::ClientConnect(const char *cpService,
  157.     HSZ& hszTopic)
  158. {
  159.     CDDECMDWrapper *pConv = NULL;
  160.  
  161.     //    Make the service name into an HSZ.
  162.     HSZ hszService = DdeCreateStringHandle(m_dwidInst, 
  163.                                            (char *) cpService,
  164.                                            CP_WINANSI);
  165.     if(hszService == NULL)    {
  166.         return(NULL);
  167.     }
  168.     
  169.     //    Establish the connection.
  170.     HCONV hConv = DdeConnect(m_dwidInst, hszService, hszTopic, NULL);
  171.     if(hConv != NULL)    {
  172.         //    We have a connection, all that's left to do is to create
  173.         //        a CDDECMDWrapper, we'll be creating it with the wrong
  174.         //        service name of course, but client connections no
  175.         //        longer really care about the service connection number,
  176.         //        all they need is the conversation handle.
  177.         pConv = new CDDECMDWrapper(m_hsz[m_ServiceName], hszTopic, hConv);
  178.     }
  179.         
  180.     //    Free off our created hsz.
  181.     DdeFreeStringHandle(m_dwidInst, hszService);
  182.     
  183.  
  184.     return(pConv);
  185. }
  186.  
  187. //    Purpose:    Figure out which wrapper is associated with a conversation.
  188. //    Arguments:    hConv    The conversation to find out about.
  189. //    Returns:    CDDECMDWrapper *    A pointer to the CDDECMDWrapper that is
  190. //                                    handling the conversation, or NULL
  191. //                                    if none is present.
  192. //    Comments:    Shouldn't ever return NULL really.
  193. //    Revision History:
  194. //        12-30-94    created GAB
  195. //        12-04-96    reused by AJ.  Probably not necessary, but you never know
  196. //                    know when we may have to do more than one conversation.
  197. CDDECMDWrapper *CDDECMDWrapper::GetConvObj(HCONV hConv)
  198. {
  199.     //    Query our static map of conversations for the object.
  200.     void *pWrap;
  201.     
  202.     if(m_ConvList.Lookup((void *)hConv, pWrap) == 0)    {
  203.         return(NULL);
  204.     }
  205.     return((CDDECMDWrapper *)pWrap);
  206. }
  207.  
  208.  
  209. //    Purpose:    Return the offset of the hsz topic string in our static
  210. //                    m_hsz array
  211. //    Arguments:    hsz    The HSZ string to find in our array
  212. //    Returns:    int    The offset into the array, also correlating to
  213. //                        it's enumerated value.  If not found, the
  214. //                        returned failure value is 0.
  215. //    Comments:    Mainly coded to remove redundant lookups.  Modularity...
  216. //    Revision History:
  217. //        12-30-94    created GAB
  218. //        12-04-96    reused by AJ.  Probably not necessary, but you never know
  219. //                    know when we may have to handle more than one topic.
  220. int CDDECMDWrapper::EnumTopic(HSZ& hsz)
  221. {
  222.     int i_retval = 0;
  223.     int i_counter;
  224.     
  225.     //    Just start looking for the HSZ string in our static array.
  226.     for(i_counter = m_TopicStart; i_counter < m_MaxHSZ; i_counter++)
  227.     {
  228.         if(m_hsz[i_counter] == hsz)    {
  229.             i_retval = i_counter;
  230.             break;
  231.         }
  232.     }
  233.     
  234.     return(i_retval);
  235. }
  236.  
  237. HDDEDATA 
  238. CALLBACK 
  239. #ifndef XP_WIN32
  240. _export 
  241. #endif
  242.  
  243. CmdLineDdeCallBack(UINT type, UINT fmt,
  244.     HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1,
  245.     DWORD dwData2)
  246. {
  247.     
  248.     
  249.     //    Depending on the class of transaction, we return different data.
  250.     if(type & XCLASS_BOOL)    {
  251.         //    Must return (HDDEDATA)TRUE or (HDDEDATA)FALSE
  252.         switch(type)    {
  253.  
  254.         case XTYP_CONNECT:    {
  255.             //    We are the server.
  256.             //    A client call the DdeConnect specifying a service and
  257.             //        topic name which we support.
  258.             HSZ& hszTopic = hsz1;
  259.             HSZ& hszService = hsz2;
  260.             
  261.             //    Deny the connection if the service name is not the
  262.             //        one we are taking connections for.
  263.             if(hszService !=
  264.                 CDDECMDWrapper::m_hsz[CDDECMDWrapper::m_ServiceName])    {
  265.                 return((HDDEDATA)FALSE);
  266.             }
  267.             
  268.             //    Now, the topic can be NULL, or it can be any one of our
  269.             //        topic names to be accepted.
  270.             if(hszTopic == NULL)    {
  271.                 return((HDDEDATA)TRUE);
  272.             }
  273.             
  274.             //    Go through all our topics, see if we match.
  275.             if(0 != CDDECMDWrapper::EnumTopic(hszTopic))    {
  276.                 return((HDDEDATA)TRUE);
  277.             }
  278.             
  279.             //    Topic not supported
  280.             return((HDDEDATA)FALSE);
  281.         }
  282.         default:
  283.             //    unknown
  284.             return((HDDEDATA)FALSE);
  285.         }
  286.         
  287.         //    Break handled here
  288.         return((HDDEDATA)FALSE);
  289.     }
  290.     else if(type & XCLASS_DATA)    {
  291.         //    Must return DDE data handle, CBR_BLOCK, or NULL        
  292.             return(NULL);
  293.     }
  294.     else if(type & XCLASS_FLAGS)    {
  295.         //    Must return DDE_FACK, DDE_BUSY, or DDE_FNOTPROCESSED
  296.         switch(type)    {
  297.         case XTYP_ADVDATA:    {
  298.             //    We are the client.
  299.             //    The server gave us a data handle.
  300.             break;
  301.         }
  302.         case XTYP_EXECUTE:    {
  303.             //    We are the server.
  304.             //    A client said XTYP_EXECUTE in DdeClientTransaction
  305.             HDDEDATA& hDataExecute = hData;
  306.             char *pData = (char *)DdeAccessData(hDataExecute, NULL);
  307.             char szCmd[_MAX_PATH+12];
  308.             strcpy ( szCmd, "[cmdline(\"" );
  309.             strcat ( szCmd, pData );
  310.             strcat ( szCmd, "\")]" );
  311.             BOOL bRetval = theApp.OnDDECommand(szCmd);
  312.             
  313.             DdeUnaccessData(hDataExecute);
  314.             return((HDDEDATA) bRetval);
  315.         }
  316.  
  317.         default:
  318.             //    unknown
  319.             return(DDE_FNOTPROCESSED);
  320.         }
  321.         
  322.         //    Break handled here
  323.         return(DDE_FNOTPROCESSED);
  324.     }
  325.     else if(type & XCLASS_NOTIFICATION)    {
  326.         //    Must return NULL, as the return value is ignored
  327.         switch(type)    {
  328.         case XTYP_ADVSTOP:    {
  329.             //    We are the server
  330.             //    A client said XTYP_ADVSTOP in DdeClientTransaction
  331.             break;
  332.         }
  333.         case XTYP_CONNECT_CONFIRM:    {
  334.             //    We are the server.
  335.             //    We returned 1 to a XTYP_CONNECT transaction.
  336.             
  337.             //    This callback is mainly to inform us of the conversation
  338.             //        handle that now exists, but we will actually be
  339.             //        creating an instance of an object to handle this
  340.             //        conversation from now on.
  341.             HSZ& hszTopic = hsz1;
  342.             HSZ& hszService = hsz2;
  343.             
  344.             //    Create the object, correctly initialized so that
  345.             //        it understands the service, topic, and conversation
  346.             //        it is handling.
  347.             //    It will add itself to the conversation list.
  348.             CDDECMDWrapper *pObject = new CDDECMDWrapper(hszService, hszTopic,
  349.                 hconv);
  350.             break;
  351.         }
  352.         case XTYP_DISCONNECT:    {
  353.             //    We are either client/server
  354.             //    The partner in the conversation called DdeDisconnect
  355.             //        causing both client/server to receive this.
  356.             
  357.             //    Find out which conversation object we are dealing with.
  358.             CDDECMDWrapper *pWrapper = CDDECMDWrapper::GetConvObj(hconv);
  359.             
  360.             //    Simply delete it.
  361.             //    The object takes care of removing itself from the list.
  362.             if(pWrapper != NULL)    {
  363.                 delete pWrapper;
  364.             }
  365.             break;
  366.         }
  367.         case XTYP_ERROR:    {
  368.             //    We are either client/server
  369.             //    A serious error has occurred.
  370.             //    DDEML doesn't have any resources left to guarantee
  371.             //        good communication.
  372.             break;
  373.         }
  374.         case XTYP_REGISTER:    {
  375.             //    We are either client/server
  376.             //    A server application used DdeNameService to register
  377.             //        a new service name.
  378.             break;
  379.         }
  380.         case XTYP_UNREGISTER:    {
  381.             //    We are either client/server
  382.             //    A server applciation used DdeNameService to unregister
  383.             //        an old service name.
  384.             break;
  385.         }
  386.         case XTYP_XACT_COMPLETE:    {
  387.             //    We are the client
  388.             //    An asynchronous tranaction, sent when the client specified
  389.             //        the TIMEOUT_ASYNC flag in DdeClientTransaction has
  390.             //        concluded.
  391.             break;
  392.         }
  393.         default:
  394.             //    unknown
  395.             return(NULL);
  396.         }
  397.         return(NULL);
  398.     }
  399.  
  400.     //    Unknown class type
  401.     return(NULL);
  402.  
  403. }
  404.  
  405.  
  406.