home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / ckoclip.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  12KB  |  355 lines

  1. /*
  2.   Authors: Frank da Cruz  (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
  3.              Columbia University Academic Information Systems, New York City.
  4.            Jeffrey E Altman (jaltman@secure-endpoints.com)
  5.              Secure Endpoints Inc., New York City
  6.  
  7.   Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New
  8.   York.
  9. */
  10.  
  11. #define INCL_WIN
  12. #define INCL_WINMLE
  13. #define INCL_GPICONTROL
  14. #define INCL_WINCLIPBOARD
  15. #define INCL_DOSPROCESS
  16. #define INCL_DOSSEMAPHORES
  17. #define INCL_DOSMEMMGR
  18. #include <os2.h>
  19. #undef COMMENT
  20. #include <stdlib.h>
  21. #include <string.h>
  22.  
  23. #include "ckoclip.h"
  24.  
  25. /* definitions & macros */
  26. #define PAPA( x)        WinQueryWindow( x, QW_PARENT)
  27. #define MENU( x)        WinWindowFromID( x, FID_MENU)
  28. #define HAB( x)         WinQueryAnchorBlock( x)
  29.  
  30. #define FCF_WPS     FCF_HIDEMAX | FCF_STANDARD & ~FCF_MINMAX
  31.  
  32. #define CT_MLE      1000
  33. #define MAXCHARS    65535
  34.  
  35. #define WM_PASSPROC     WM_USER + 0
  36. #define WM_GETDATA      WM_USER + 1
  37. #define WM_PUTDATA      WM_USER + 2
  38.  
  39. /* function prototypes */
  40. int main( void) ;
  41. MRESULT EXPENTRY ClientWndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) ;
  42.  
  43. /* globals */
  44. HAB hab ;                              /* Handle to the Anchor Block */
  45. HWND hwndFrame,                        /* Handle to the Frame Window */
  46.      hwndClient ;                      /* Handle to the Client Window ! */
  47. int  killthread = 0 ;                  /* Signal to Server thread to die */
  48. HMUX hmuxClipbrdSrv = 0 ;              /* Only allow one client at a time */
  49. HEV hevClipbrdGet  = 0 ;               /* Signal to get clipboard data */
  50. HEV hevClipbrdPut  = 0 ;               /* Signal to put clipboard data */
  51. HEV hevClipbrdReady = 0 ;              /* The data is ready for client */
  52. HEV hevClipbrdData = 0 ;               /* Let the client know its ready */
  53. HEV hevClipbrdDone = 0 ;               /* The Client is done; reset */
  54. PSZ pSharedMem =0;                     /* The shared memory buffer */
  55.  
  56.  
  57. /* This function is the Clipboard Server thread.  It handles all
  58.    communication with our clients via Named Shared Semaphores.
  59.    We can't access the clipboard from here, so we post a message
  60.    to our message queue thread when we need the clipboard data.
  61.    The Window Procedure then gets the data and signals us via a
  62.    private semaphore that it the data is ready.  At that time
  63.    we signal our client, and wait for the client to complete.
  64.    If the client, doesn't release us we will wait forever.  But better
  65.    that then allow two clients to possibly crash into each other
  66. */
  67. void
  68. clipsrv( void * param )
  69. {
  70.   ULONG   clipsize =0;
  71.   PBYTE * clipdata =0;
  72.   ULONG postcount =0;
  73.   APIRET rc = 0 ;
  74.   HMUX    hmuxWaitForWork = 0 ;
  75.   SEMRECORD work_rec[2] ;
  76.   ULONG jobtype ;
  77. #define GETTEXT 0L
  78. #define PUTTEXT 1L
  79.  
  80.   rc = DosAllocSharedMem( (PPVOID) &pSharedMem,
  81.           "\\SHAREMEM\\CKERMIT\\CLIPBRD\\DATA",
  82.           MAXCHARS, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE ) ;
  83.  
  84.   work_rec[0].hsemCur = (HSEM) hevClipbrdGet ;
  85.   work_rec[0].ulUser  = GETTEXT ;
  86.   work_rec[1].hsemCur = (HSEM) hevClipbrdPut ;
  87.   work_rec[1].ulUser  = PUTTEXT ;
  88.  
  89.   rc = DosCreateMuxWaitSem( NULL, &hmuxWaitForWork, 2, work_rec,
  90.         DCMW_WAIT_ANY | DC_SEM_SHARED ) ;
  91.  
  92.   while ( !killthread ) {
  93.     pSharedMem[0] = '\0' ;
  94.  
  95.     /* Wait for something to do */
  96.     rc = DosWaitMuxWaitSem( hmuxWaitForWork, SEM_INDEFINITE_WAIT, &jobtype ) ;
  97.  
  98.     switch ( jobtype ) {
  99.         case GETTEXT:
  100.             rc = DosResetEventSem( hevClipbrdGet, &postcount ) ;
  101.  
  102.             WinPostMsg( hwndClient, WM_GETDATA, 0, 0 );
  103.  
  104.             rc = DosWaitEventSem( hevClipbrdReady, SEM_INDEFINITE_WAIT );
  105.             rc = DosResetEventSem( hevClipbrdReady, &postcount );
  106.  
  107.             /* Now let the requester know its ready */
  108.  
  109.             rc = DosPostEventSem( hevClipbrdData ) ;
  110.  
  111.             /* Now wait for the requester to finish using the memory */
  112.  
  113.             rc = DosWaitEventSem( hevClipbrdDone, SEM_INDEFINITE_WAIT ) ;
  114.             rc = DosResetEventSem( hevClipbrdDone, &postcount ) ;
  115.             break;
  116.  
  117.         case PUTTEXT:
  118.             rc = DosResetEventSem( hevClipbrdPut, &postcount ) ;
  119.  
  120.             /* There is text in the shared memory to be sent to the Clipboard */
  121.             /* so let the Window Message thread know                          */
  122.  
  123.             WinPostMsg( hwndClient, WM_PUTDATA, 0 , 0 ) ;
  124.  
  125.             /* Wait for the Window Message thread to finish the Copy */
  126.             rc = DosWaitEventSem( hevClipbrdReady, SEM_INDEFINITE_WAIT );
  127.             rc = DosResetEventSem( hevClipbrdReady, &postcount );
  128.  
  129.             /* Let the client know we are Done */
  130.             rc = DosPostEventSem( hevClipbrdDone ) ;
  131.             break;
  132.         }
  133.  
  134.     }
  135.     rc = DosCloseMuxWaitSem( hmuxWaitForWork ) ;
  136.     rc = DosFreeMem( pSharedMem ) ;
  137. }
  138.  
  139. int
  140. initserver( void )
  141. {
  142.     APIRET rc ;
  143.  
  144.     if ( rc = DosCreateMutexSem( "\\SEM32\\CKERMIT\\CLIPBRD\\MUX",
  145.         &hmuxClipbrdSrv, DC_SEM_SHARED, TRUE ) )
  146.         return 1 ;
  147.  
  148.     if ( rc = DosCreateEventSem( "\\SEM32\\CKERMIT\\CLIPBRD\\GET", &hevClipbrdGet,
  149.         DC_SEM_SHARED, FALSE ) ) {
  150.             DosCloseMutexSem( hmuxClipbrdSrv ) ;
  151.             return 1 ;
  152.             }
  153.     if ( rc = DosCreateEventSem( "\\SEM32\\CKERMIT\\CLIPBRD\\DATA", &hevClipbrdData,
  154.         DC_SEM_SHARED, FALSE ) ) {
  155.             DosCloseMutexSem( hmuxClipbrdSrv ) ;
  156.             DosCloseEventSem( hevClipbrdGet ) ;
  157.             return 1 ;
  158.             }
  159.     if ( rc = DosCreateEventSem( "\\SEM32\\CKERMIT\\CLIPBRD\\DONE", &hevClipbrdDone,
  160.         DC_SEM_SHARED, FALSE ) ) {
  161.             DosCloseMutexSem( hmuxClipbrdSrv ) ;
  162.             DosCloseEventSem( hevClipbrdGet ) ;
  163.             DosCloseEventSem( hevClipbrdData ) ;
  164.             return 1 ;
  165.             }
  166.  
  167.     if ( rc = DosCreateEventSem( NULL, &hevClipbrdReady, 0, FALSE ) ) {
  168.             DosCloseMutexSem( hmuxClipbrdSrv ) ;
  169.             DosCloseEventSem( hevClipbrdGet ) ;
  170.             DosCloseEventSem( hevClipbrdData ) ;
  171.             DosCloseEventSem( hevClipbrdDone ) ;
  172.             return 1 ;
  173.             }
  174.     if ( rc = DosCreateEventSem( "\\SEM32\\CKERMIT\\CLIPBRD\\PUT", &hevClipbrdPut,
  175.         DC_SEM_SHARED, FALSE ) ) {
  176.             DosCloseMutexSem( hmuxClipbrdSrv ) ;
  177.             DosCloseEventSem( hevClipbrdGet ) ;
  178.             DosCloseEventSem( hevClipbrdData ) ;
  179.             DosCloseEventSem( hevClipbrdDone ) ;
  180.             DosCloseEventSem( hevClipbrdReady ) ;
  181.             return 1 ;
  182.             }
  183.     return 0 ;
  184. }
  185.  
  186. void
  187. killserver( void )
  188. {
  189.     DosRequestMutexSem( hmuxClipbrdSrv, SEM_INDEFINITE_WAIT ) ;
  190.     killthread = 1 ;
  191.     DosCloseMutexSem( hmuxClipbrdSrv ) ;
  192.     DosCloseEventSem( hevClipbrdGet ) ;
  193.     DosCloseEventSem( hevClipbrdData ) ;
  194.     DosCloseEventSem( hevClipbrdDone ) ;
  195.     DosCloseEventSem( hevClipbrdPut ) ;
  196. }
  197.  
  198. /* Main thread.  Allocate all semaphores.  If we can't it probably
  199.    means that another copy of is already running.  So just die.
  200. */
  201.  
  202. int main( void)
  203. {
  204.     CHAR szWindowTitle[255] ;
  205.     HMQ hmq ;
  206.     QMSG qmsg ;
  207.     ULONG flFrameFlags = FCF_WPS & ~FCF_ACCELTABLE ;
  208.     APIRET rc ;
  209.  
  210.     hab = WinInitialize( 0) ;
  211.     hmq = WinCreateMsgQueue( hab, 0L) ;
  212.  
  213.     if ( initserver() ) {  /* couldn't create semaphores */
  214.         WinLoadString(  hab, NULLHANDLE, ST_CREATION_ERROR,
  215.                         sizeof( szWindowTitle), szWindowTitle) ;
  216.         WinMessageBox( HWND_DESKTOP, HWND_DESKTOP, szWindowTitle,
  217.             (PSZ) NULL, 1, MB_ERROR  ) ;
  218.         return 1 ;
  219.         }
  220.     else {
  221.         /* load window title from resource file */
  222.         WinLoadString(  hab, NULLHANDLE, ST_WINDOWTITLE,
  223.                         sizeof( szWindowTitle), szWindowTitle) ;
  224.  
  225.         /* create main window */
  226.         hwndFrame = WinCreateStdWindow( HWND_DESKTOP,
  227.                                         0,
  228.                                         &flFrameFlags,
  229.                                         WC_MLE,
  230.                                         szWindowTitle,
  231.                                         WS_CLIPCHILDREN,
  232.                                         NULLHANDLE,
  233.                                         RS_ALL,
  234.                                         &hwndClient) ;
  235.  
  236.         WinSetWindowPos( hwndFrame, HWND_BOTTOM, 0L, 0L, 450L, 100L,
  237.             SWP_SIZE | SWP_SHOW | SWP_ZORDER) ;
  238.         WinShowWindow( hwndFrame, FALSE ) ;
  239.  
  240.         /* subclass the MLE */
  241.         WinSendMsg( hwndClient, WM_PASSPROC,
  242.             MPFROMP( WinSubclassWindow( hwndClient, ClientWndProc)), 0L) ;
  243.  
  244.         /* Start processing client requests */
  245.         _beginthread( clipsrv, NULL, 65535, NULL ) ;
  246.         rc = DosReleaseMutexSem( hmuxClipbrdSrv ) ;
  247.  
  248.         while( WinGetMsg( hab, &qmsg, NULLHANDLE, 0L, 0L))
  249.             WinDispatchMsg( hab, &qmsg) ;
  250.  
  251.         /* destroy resources */
  252.         killserver() ;
  253.         WinDestroyWindow (hwndFrame) ;
  254.         WinDestroyMsgQueue (hmq) ;
  255.         WinTerminate (hab) ;
  256.         }
  257.     return 0L ;
  258. }
  259.  
  260. /* The Clients Window Procedure.  It is here that we actually get the
  261.    Clipboard Data and place it into the shared memory.
  262. */
  263. MRESULT EXPENTRY ClientWndProc( HWND hwnd,
  264.                                 ULONG msg,
  265.                                 MPARAM mp1,
  266.                                 MPARAM mp2)
  267. {
  268.     static PFNWP pfnwp ;
  269.     static HWND hmenu ;
  270.     APIRET rc ;
  271.     PSZ pClipboard ;
  272.  
  273.     switch( msg)
  274.     {
  275.         case WM_PASSPROC:
  276.             pfnwp = (PFNWP)mp1 ;
  277.             /* limit text to MAXCHARS characters and make it readonly*/
  278.             WinSendMsg( hwnd, MLM_SETTEXTLIMIT, MPFROMLONG(MAXCHARS), 0L) ;
  279.             WinSendMsg( hwnd, MLM_SETREADONLY, MPFROMLONG(1L), 0L) ;
  280.  
  281.             /* get the menu handle */
  282.             hmenu = MENU(PAPA(hwnd)) ;
  283.             return 0L ;
  284.  
  285.         case WM_GETDATA:
  286.           /* Get the data from the clipboard */
  287.           rc = WinOpenClipbrd(hab) ;
  288.           if ( rc ) {
  289.               pClipboard = (PSZ) WinQueryClipbrdData( hab, CF_TEXT ) ;
  290.  
  291.               /* Copy it to our Shared Memory */
  292.               if ( pClipboard )
  293.                 strcpy( pSharedMem, pClipboard ) ;
  294.  
  295.               WinCloseClipbrd(hab) ;
  296.               }
  297.  
  298.             /* set text in the MLE window */
  299.             WinSetWindowText( hwnd, pSharedMem) ;
  300.  
  301.             DosPostEventSem( hevClipbrdReady );
  302.  
  303.             return 0L;
  304.  
  305.         case WM_PUTDATA:
  306.             /* The data is in our named shared memory */
  307.             /* we must allocate shared memory to give to the clipboard */
  308.             /* copy the text into it */
  309.             /* and pass it off to the clipboard */
  310.  
  311.             rc = DosAllocSharedMem( (PPVOID) &pClipboard,
  312.                 NULL, strlen(pSharedMem)+1, PAG_COMMIT | PAG_WRITE | OBJ_GIVEABLE );
  313.  
  314.             if ( pClipboard ) {
  315.                 strcpy( pClipboard, pSharedMem ) ;
  316.                 rc = WinOpenClipbrd(hab);
  317.                 if ( rc ) {
  318.                     rc = WinSetClipbrdData( hab, (ULONG) pClipboard, CF_TEXT,
  319.                         CFI_POINTER ) ;
  320.                     WinCloseClipbrd( hab ) ;
  321.                     WinSetWindowText( hwnd, pSharedMem ) ;
  322.                     }
  323.                 else {
  324.                     WinSetWindowText( hwnd, "Unable to open Clipboard." ) ;
  325.                     }
  326.                 }
  327.             else {
  328.                 WinSetWindowText( hwnd, "Unable to allocate Shared Memory for PUT operation.");
  329.                 }
  330.             DosPostEventSem( hevClipbrdReady );
  331.             return 0L;
  332.  
  333.         case WM_INITMENU:
  334.             break ;
  335.  
  336.         case WM_COMMAND:
  337.             switch( COMMANDMSG( &msg) -> cmd)
  338.             {
  339.                 case MN_EXIT:
  340.                     WinPostMsg( hwnd, WM_QUIT, NULL, NULL) ;
  341.                     break ;
  342.  
  343.                 default:
  344.                     break ;
  345.             }
  346.             break ;
  347.  
  348.         default:
  349.             break;
  350.     }
  351.     return (*pfnwp)( hwnd, msg, mp1, mp2) ;
  352. }
  353.  
  354.  
  355.