home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / wsftp32 / ws_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  67.6 KB  |  2,089 lines

  1. /***************************************************************************
  2.   Windows Sockets FTP Client Application
  3.  
  4.   Written by:
  5.       John A. Junod             Internet: <junodj@gordon-emh2.army.mil>
  6.       267 Hillwood Street                 <zj8549@trotter.usma.edu>
  7.       Martinez, GA 30907      Compuserve: 72321,366 
  8.  
  9.   This program executable and all source code is released into the public
  10.   domain.  It would be nice (but is not required) to give me a little 
  11.   credit for any use of this code.
  12.  
  13.   The user interface for this FTP client is designed with the novice FTP user
  14.   in mind.  Usage should (??) be obvious with the possible exception of the
  15.   the transfer mode; ascii, binary or l8.  All controls are standard Windows
  16.   controls.
  17.  
  18.   My development and testing was all completed at home on two 386 PC's using
  19.   the Trumpet Windows Sockets DLL Alpha 15 with NCSA Telnet and WinQVT/Net 2.6
  20.   and 3.9 as the remote host.  Source code may be compiled with Borland C++
  21.   in large mode.
  22.  
  23.   Some code concepts and names are based on code that is copyright by the
  24.   Regents of the University of California or code published in UNIX Network
  25.   Programming by W. Richard Stevens or code in WATTCP or other public sources.
  26.   The rest is based on my knowledge of Windows programming and my 
  27.   interpretation of RFC 969 and the Windows Sockets API version 1.1.
  28.  
  29.   THE INFORMATION AND CODE PROVIDED IS PROVIDED AS IS WITHOUT WARRANTY 
  30.   OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  31.   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  32.   PURPOSE. IN NO EVENT SHALL JOHN A. JUNOD BE LIABLE FOR ANY DAMAGES 
  33.   WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS 
  34.   OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF JOHN A. JUNOD HAS BEEN 
  35.   ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  36.  
  37. *****************************************************************************/
  38. // modified extensively by l kahn for windows nt and multi threading
  39. // turn off list windows for mirror operation
  40.  
  41. //----------------------
  42. #include "ws_glob.h"
  43. #include "WS_ftp.H"
  44. #include "version.h"
  45. //----------------------
  46. #include <stdarg.h>
  47. #include <ctype.h>
  48. #include <shellapi.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51.  
  52.  // lgk new debugging variable
  53. BOOLEAN DEBUGGING_ON = FALSE;
  54.  
  55. int selects[256];
  56. extern char szInitDir[];
  57. HBRUSH hbrGray1,hbrGray2,hbrWhite;
  58. extern HWND hWndDbg;
  59. BOOLEAN connectpending = FALSE;
  60. volatile BOOLEAN aborttimerexpired = FALSE;
  61.  
  62.  
  63. // lgk new stuff for multiple threads
  64. extern int check_command_line();
  65. CRITICAL_SECTION busy_variable;
  66. BOOLEAN busy = FALSE;
  67. HWND globalhWnd;
  68. WPARAM globalwParam;
  69. DWORD threadid;
  70. HANDLE threadhandle;
  71.  
  72. #ifndef USEASYNC
  73. SubProcessAsync(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
  74. {
  75.   return(FALSE);
  76. }
  77. #endif
  78.  
  79. // lgk new routine to get the local search string
  80.  
  81. extern char *localsearchstring();
  82.      
  83.  
  84. int VerifyDelete(LPSTR fname)
  85. {
  86.   wsprintf(szDlgPrompt,"Are you sure you want to delete \"%s\"?",fname);
  87.   return(MessageBox(hWndMain,szDlgPrompt,"Verify Deletion",MB_YESNO)==IDYES);
  88. }
  89.   
  90.  VOID CALLBACK myaborttimerproc(wind,msg,idevent,systime)
  91.  HWND wind;
  92.  UINT msg;
  93.  UINT idevent;
  94.  DWORD systime;
  95.  {
  96.         KillTimer(wind,21);
  97.         aborttimerexpired = TRUE;
  98.  }
  99.  
  100. void turnofflistwindows()
  101.  
  102.  
  103.  {
  104.  
  105.   BOOL rv;
  106.  
  107.   rv = ShowWindow(hLbxLDir,SW_HIDE);
  108.   rv = ShowWindow(hLbxLFiles,SW_HIDE);
  109.   rv = ShowWindow(hLbxRDir,SW_HIDE);
  110.   rv = ShowWindow(hLbxRFiles,SW_HIDE);
  111.  
  112.   EnableWindow(hBtnLCWD,FALSE);
  113.   EnableWindow(hBtnLMKD,FALSE);
  114.   EnableWindow(hBtnLRMD,FALSE);
  115.   EnableWindow(hLdirBox,FALSE);
  116.   EnableWindow(hRdirBox,FALSE);
  117.   EnableWindow(hBtnLDisplay,FALSE);
  118.   EnableWindow(hBtnLREN,FALSE);
  119.   EnableWindow(hBtnLDEL,FALSE);
  120.  
  121.   
  122.  }
  123.  
  124.  void turnonlistwindows()
  125.  
  126.  {
  127.  
  128.  BOOL rv;
  129.  
  130.   rv = ShowWindow(hLbxLDir,SW_SHOW);
  131.   rv = ShowWindow(hLbxLFiles,SW_SHOW);
  132.   rv = ShowWindow(hLbxRDir,SW_SHOW);
  133.   rv = ShowWindow(hLbxRFiles,SW_SHOW);
  134.  
  135.   EnableWindow(hBtnLCWD,TRUE);
  136.   EnableWindow(hBtnLMKD,TRUE);
  137.   EnableWindow(hBtnLRMD,TRUE);
  138.   EnableWindow(hLdirBox,TRUE);
  139.   EnableWindow(hRdirBox,TRUE);
  140.   EnableWindow(hBtnLDisplay,TRUE);
  141.   EnableWindow(hBtnLREN,TRUE);
  142.   EnableWindow(hBtnLDEL,TRUE);
  143.  
  144.  }
  145.   
  146. void MakeLower(LPSTR str) {
  147.   while(*str) {
  148.     *str=tolower(*str);
  149.     str++;
  150.   }
  151. }
  152. // lgk function to set busy variable so that we don't get collisions
  153. void set_busy(invalue)
  154.  BOOLEAN invalue;
  155.    {
  156.      EnterCriticalSection(&busy_variable);
  157.      busy = invalue;
  158.      LeaveCriticalSection(&busy_variable);
  159.    }
  160.    
  161. BOOLEAN check_busy()
  162.    {
  163.      BOOLEAN rvalue;
  164.       
  165.      EnterCriticalSection(&busy_variable);
  166.      rvalue = busy;
  167.      LeaveCriticalSection(&busy_variable);
  168.      return rvalue;
  169.    }
  170.  
  171.   /* ------------------------------------------------------------------------------------------- */
  172.      
  173. // lgk new functions that will run in a thread
  174.  
  175. DWORD local_to_remote_fx()
  176. {
  177.     
  178.   int nIndex,nRC;
  179.  
  180.             u_char tmp[300];
  181.             char localname[256];
  182.             char remotename[256];
  183.             int count;
  184.  
  185.             count=SendMessage(hLbxLFiles,
  186.                       LB_GETSELITEMS,256,(LPARAM)(int far *)selects);
  187.             if(count>0 && count!=LB_ERR)
  188.               {
  189.                EnableWindow(hBtnAbort,TRUE);
  190.              for(nIndex=0;nIndex<count;nIndex++)
  191.                  {
  192.                 SendMessage(hLbxLFiles,LB_GETTEXT,selects[nIndex],
  193.                                  (LONG)localname);
  194.                 lstrcpy(remotename,localname);
  195.                 if(bInteractive) 
  196.                   StdInput(remotename,"Enter remote file name for %s:",localname);
  197.                 wsprintf(tmp,"sending %s as %s (%u of %u)",localname,remotename,nIndex+1,count);
  198.                 SendMessage(hTxtStatus,WM_SETTEXT,0,(LPARAM)tmp);
  199.                 wsprintf(tmp,"STOR %s",remotename);
  200.                 nRC=SendFile(ctrl_socket,tmp,(LPSTR)localname,fType);
  201.                 if(nRC!=2) break;
  202.                  }  
  203.               GetRemoteDirForWnd(globalhWnd);
  204.           }
  205. set_busy(FALSE);
  206. EnableWindow(hBtnAbort,FALSE);
  207. return 0;
  208. }
  209.  
  210.  
  211. /* ---------------------------------------------------------------------------------------------- */
  212.      
  213. // lgk new functions that will run in a thread
  214. // other version that does not update directory
  215.  
  216. DWORD local_to_remote_fx2()
  217. {
  218.     
  219.   int nIndex,nRC;
  220.  
  221.             u_char tmp[300];
  222.             char localname[256];
  223.             char remotename[256];
  224.             int count;
  225.  
  226.             count=SendMessage(hLbxLFiles,
  227.                       LB_GETSELITEMS,256,(LPARAM)(int far *)selects);
  228.             if(count>0 && count!=LB_ERR)
  229.               {
  230.                EnableWindow(hBtnAbort,TRUE);
  231.              for(nIndex=0;nIndex<count;nIndex++)
  232.                  {
  233.                 SendMessage(hLbxLFiles,LB_GETTEXT,selects[nIndex],
  234.                                  (LONG)localname);
  235.                 lstrcpy(remotename,localname);
  236.                 if(bInteractive) 
  237.                   StdInput(remotename,"Enter remote file name for %s:",localname);
  238.                 wsprintf(tmp,"sending %s as %s (%u of %u)",localname,remotename,nIndex+1,count);
  239.                 SendMessage(hTxtStatus,WM_SETTEXT,0,(LPARAM)tmp);
  240.                 wsprintf(tmp,"STOR %s",remotename);
  241.                 nRC=SendFile(ctrl_socket,tmp,localname,fType);
  242.                 if(nRC!=2) break;
  243.                  }  
  244.           }
  245. set_busy(FALSE);
  246. EnableWindow(hBtnAbort,FALSE);
  247. return 0;
  248. }
  249.  
  250.  
  251. /* ---------------------------------------------------------------------------------------------- */
  252.  
  253.  
  254. DWORD local_to_remote_mirror_fx()
  255. {
  256.   char localdirname[256];
  257.   int count,count2, count3;
  258.   char ldirsave[_MAX_PATH];
  259.   char rdirsave[_MAX_PATH];
  260.   int nIndex,nRC;
  261.   int lselects[256];
  262.  
  263.   /* different from renmote to local we must skip the drives here which show up as local dirs ie [-a-]
  264.     also make sure selected strings dont have the drive in it ..
  265.     */
  266.  
  267.  
  268.  
  269.             count=SendMessage(hLbxLDir,LB_GETSELITEMS,
  270.                                  256,(LPARAM)(int *)lselects);
  271.             if(count>0 && count!=LB_ERR)
  272.               {
  273.  
  274.                 /* Get the current working directory: */
  275.                 if (_getcwd(ldirsave, _MAX_PATH ) != NULL )
  276.                   {
  277.                   SendMessage(hTxtRDir,WM_GETTEXT,_MAX_PATH,(LONG)rdirsave);
  278.                   EnableWindow(hBtnAbort,TRUE);
  279.                   turnofflistwindows();
  280.                   for(nIndex=0;nIndex<count;nIndex++)
  281.                    {
  282.                      // skip the first one if selected as it is bogus
  283.                      if (lselects[nIndex] != 0)
  284.                        {
  285.                          SendMessage(hLbxLDir,LB_GETTEXT,lselects[nIndex],
  286.                                  (LONG)localdirname);
  287.  
  288.                           if (strncmp(localdirname,"[-",2) != 0)
  289.                             {
  290.                              
  291.                            nRC=DoMKD(ctrl_socket,localdirname);
  292.                            if (nRC == 550)
  293.                             {
  294.                               DoPrintf("Warning failure creating remote directory %s, directory may already exist.",
  295.                                        localdirname);
  296.                             }
  297.                            else if (nRC == FTP_ERROR)
  298.                             {
  299.                              DoPrintf("Aborting since remote mkdir failed...ecode = %d",nRC);
  300.                              set_busy(FALSE);
  301.                              EnableWindow(hBtnAbort,FALSE);
  302.                              turnonlistwindows();
  303.                              return 0;
  304.                            }
  305.                            else
  306.                             {
  307.                               // now change to the dir
  308.                             ++totaldirscreated;
  309.                             DoPrintf("Created remote directory %s",localdirname);
  310.                             nRC=DoCWD(ctrl_socket,localdirname);
  311.                             if(nRC==FTP_COMPLETE)
  312.                               {
  313.                                GetRemoteDirForWnd(globalhWnd);
  314.                    --totalfilestransfered;
  315.                        }
  316.                             else
  317.                              {
  318.                                DoPrintf("Aborting since remote cwd failed...");
  319.                                set_busy(FALSE);
  320.                                EnableWindow(hBtnAbort,FALSE);
  321.                                turnonlistwindows();
  322.                                return 0;
  323.                             }
  324.                             }
  325.                             
  326.                          chdir(localdirname);
  327.                          GetLocalDirForWnd(globalhWnd);
  328.                
  329.                   // now change the remote directory also and do a list
  330.  
  331.              // now go through everything in the file window and get it
  332.  
  333.             count2=SendMessage(hLbxLFiles,LB_GETCOUNT,0,0);
  334.             if(count2>0 && count2!=LB_ERR)
  335.               {
  336.  
  337.                count3=SendMessage(hLbxLFiles,LB_SELITEMRANGEEX,
  338.                                  (WPARAM)0 ,(LPARAM) count2);
  339.                   if (count3 != LB_ERR)
  340.                     {
  341.                       // now that this worked ok call the function to get them
  342.                       set_busy(TRUE);
  343.                       local_to_remote_fx2();
  344.                       set_busy(FALSE);
  345.                     }
  346.                   else
  347.                     {
  348.                     DoPrintf("Aborting since local file selection failed...");
  349.                     set_busy(FALSE);
  350.                     EnableWindow(hBtnAbort,FALSE);
  351.                     turnonlistwindows();
  352.                     return 0;
  353.             }  
  354.               }
  355.               
  356.              // now we got all files in this directory so select all dirs
  357.              // under it and recall ourself
  358.              // then cd back to orig directory so we can continue
  359.              // with next dir at this level
  360.              // ignore first dir which is always ..
  361.  
  362.             count2=SendMessage(hLbxLDir,LB_GETCOUNT,0,0);
  363.             if(count2>1 && count2!=LB_ERR)
  364.               {
  365.  
  366.                count3=SendMessage(hLbxLDir,LB_SELITEMRANGEEX,
  367.                                  (WPARAM)1 ,(LPARAM) count2);
  368.                   if (count3 != LB_ERR)
  369.                     {
  370.                       // now that this worked ok call ourself to recurse
  371.                       local_to_remote_mirror_fx();
  372.                     }
  373.               }
  374.              
  375.             // now cd back to the original dir so we can continue
  376.             chdir(ldirsave);
  377.             GetLocalDirForWnd(globalhWnd);
  378.             nRC=DoCWD(ctrl_socket,rdirsave);
  379.             if(nRC==FTP_COMPLETE)
  380.               {
  381.                GetRemoteDirForWnd(globalhWnd);
  382.            --totalfilestransfered; // decrement twice for both remote operations
  383.  
  384.               }
  385.               else
  386.                {
  387.                 DoPrintf("Aborting since remote cwd failed...");
  388.                 set_busy(FALSE);
  389.                 EnableWindow(hBtnAbort,FALSE);
  390.                 turnonlistwindows();
  391.                 return 0;
  392.                }
  393.  
  394.                 } // skip drive selection
  395.                } // skip bogus .. selection
  396.             // continue the loop
  397.                    } // end of loop
  398.                   } // end of getcwd ok
  399.           } // end of count ok
  400.  
  401. // print the totals
  402.  if (totalfilestransfered > 0)
  403.     { 
  404.       char str1[30];
  405.       char str2[30];
  406.  
  407.      if (totalfilestransfered == 1)
  408.       strcpy(str1,"file");
  409.       else strcpy(str1,"files");
  410.      
  411.      if (totaldirscreated == 1)
  412.        strcpy(str2,"directory");
  413.        else strcpy(str2,"directories");
  414.        
  415.      DoPrintf("%ld %s tranmitted, %ld %s created.",
  416.       totalfilestransfered,str1,totaldirscreated,str2);
  417.     }
  418. if (totaltimefortransfer > 0)
  419.   {
  420.     DoPrintf("%ld bytes tranfered in %.2f seconds, (%3.2fKbytes/sec).",
  421.       totalbytestransfered,(float)totaltimefortransfer,
  422.       (float)totalbytestransfered/1024.000/(float)totaltimefortransfer);
  423.   }
  424.  
  425. mirrorinprogress = FALSE;
  426. set_busy(FALSE);
  427. EnableWindow(hBtnAbort,FALSE);
  428. turnonlistwindows();
  429. return 0;
  430.  
  431. }
  432.  
  433. /* -------------------------------------------------------------- */
  434. DWORD remote_mkdir_fx()
  435. {
  436.     
  437.   int nRC;
  438.  
  439.   if(StdInput(NULL,"Enter new remote directory name:"))
  440.   if((nRC=DoMKD(ctrl_socket,szDlgEdit))==FTP_COMPLETE)
  441.     {
  442.       GetRemoteDirForWnd(globalhWnd);
  443.     }
  444. set_busy(FALSE);
  445. EnableWindow(hBtnAbort,FALSE);
  446. return 0;
  447. }
  448.  
  449. /* ---------------------------------------- */
  450. DWORD remote_rmdir_fx()
  451. {
  452.     
  453.   int nIndex,nRC;
  454.  
  455.   if((nIndex=SendMessage(hLbxRDir,LB_GETCURSEL,0,0L))!=LB_ERR)
  456.     {
  457.        SendMessage(hLbxRDir,LB_GETTEXT,nIndex,(LONG)szMsgBuf2);
  458.        if(VerifyDelete(szMsgBuf2))
  459.          if((nRC=DoRMD(ctrl_socket,szMsgBuf2))==FTP_COMPLETE)
  460.                   GetRemoteDirForWnd(globalhWnd);
  461.     }
  462. set_busy(FALSE);
  463. EnableWindow(hBtnAbort,FALSE);
  464. return 0;
  465.  
  466. /* ------------------------------------------------- */
  467.  
  468. DWORD remote_list_fx()
  469.   {
  470.     
  471.    GetRemoteDirForWnd(globalhWnd);
  472. EnableWindow(hBtnAbort,TRUE);
  473. set_busy(FALSE);
  474. EnableWindow(hBtnAbort,FALSE);
  475. return 0;
  476. }
  477.  
  478. /* ----------------------------- */
  479. DWORD remote_delete_fx()
  480. {
  481.     
  482.   int nIndex,nRC;
  483.  
  484.   int count;
  485.   count=SendMessage(hLbxRFiles,LB_GETSELITEMS,
  486.                                  256,(LPARAM)(int far *)selects);
  487.   if(count>0 && count!=LB_ERR)
  488.       {
  489.        for(nIndex=0;nIndex<count;nIndex++)
  490.          {
  491.            SendMessage(hLbxRFiles,LB_GETTEXT,selects[nIndex],
  492.                                  (LONG)szDlgEdit);
  493.            if(VerifyDelete(szDlgEdit))
  494.              nRC=DoDELE(ctrl_socket,szDlgEdit);
  495.          } 
  496.               GetRemoteDirForWnd(globalhWnd);
  497.       }
  498. set_busy(FALSE);
  499. EnableWindow(hBtnAbort,FALSE);
  500. return 0;
  501. }
  502.  
  503. /* ----------------------------------------------------------- */
  504. DWORD remote_rename_fx()
  505. {
  506.     
  507.   int nIndex,nRC;
  508.  
  509.           if((nIndex=SendMessage(hLbxRFiles,LB_GETCURSEL,
  510.                 0,0L))!=LB_ERR)
  511.           {
  512.             SendMessage(hLbxRFiles,LB_GETTEXT,nIndex,
  513.                                (LONG)szMsgBuf2);
  514.                 if(StdInput(NULL,"Enter new name for \"%s\":",szMsgBuf2))
  515.                 if((nRC=command(ctrl_socket,"RNFR %s",szMsgBuf2))==FTP_CONTINUE)
  516.                 if((nRC=command(ctrl_socket,"RNTO %s",szDlgEdit))==FTP_COMPLETE)
  517.                     GetRemoteDirForWnd(globalhWnd);
  518.           }
  519. set_busy(FALSE);
  520. EnableWindow(hBtnAbort,FALSE);
  521. return 0;
  522. }
  523.  
  524. /* ----------------------------------------------------------- */
  525. DWORD remote_cwd_fx()
  526. {
  527.     
  528.   int nIndex,nRC;
  529.   int count = SendMessage(hLbxRDir,LB_GETSELCOUNT,
  530.                 0,0L);
  531.   int count2 = 0;
  532.             
  533.             if (count > 1)
  534.               {
  535.                 DoPrintf("Only 1 directory can be selected for the chdir operation.");
  536.               }  
  537.             else if (count == 0)
  538.              { // ok case so ask
  539.  
  540.               if(StdInput(NULL,"Enter remote directory name:")) 
  541.               if((nRC=DoCWD((SOCKET)ctrl_socket,szDlgEdit))==FTP_COMPLETE)
  542.               GetRemoteDirForWnd(globalhWnd);
  543.  
  544.          }
  545.              
  546.            else // (count == 1)
  547.              {
  548.                 count2=SendMessage(hLbxRDir,
  549.                       LB_GETSELITEMS,256,(LPARAM)(int far *)selects);
  550.                  nIndex = selects[0];
  551.  
  552.                 EnableWindow(hBtnAbort,TRUE);
  553.                 SendMessage(hLbxRDir,LB_GETTEXT,nIndex,
  554.                                       (LONG)szMsgBuf2);
  555.                 nRC=DoCWD(ctrl_socket,szMsgBuf2);
  556.                 if(nRC==FTP_COMPLETE)
  557.                    GetRemoteDirForWnd(globalhWnd);
  558.              }
  559.  
  560.   
  561. set_busy(FALSE);
  562. EnableWindow(hBtnAbort,FALSE);
  563. return 0;
  564. }
  565.  
  566. /* ----------------------------------------------------------- */
  567. DWORD remote_to_local_fx()
  568. {
  569.   char tmp[300];
  570.   char remotename[256];
  571.   char localname[256];
  572.   char shortname[80];
  573.   int count;
  574.  
  575.   int nIndex,nRC;
  576.  
  577.             count=SendMessage(hLbxRFiles,LB_GETSELITEMS,
  578.                                  256,(LPARAM)(int far *)selects);
  579.             if(count>0 && count!=LB_ERR)
  580.               {
  581.                   EnableWindow(hBtnAbort,TRUE);
  582.                   for(nIndex=0;nIndex<count;nIndex++)
  583.                    {
  584.                      SendMessage(hLbxRFiles,LB_GETTEXT,selects[nIndex],
  585.                                  (LONG)remotename);
  586.                      MakeLocalName(localname,shortname,remotename);
  587.                      if(bInteractive)
  588.                       StdInput(localname,"Enter local file name for %s:",remotename);
  589.                       DoPrintf("receiving %s as %s (%u of %u)",
  590.                          remotename,localname,nIndex+1,count);
  591.                       wsprintf(tmp,"RETR %s",remotename);
  592.                       nRC=RetrieveFile((SOCKET)ctrl_socket,(LPSTR)tmp,
  593.                         (LPSTR)localname,(LPSTR)shortname,fType);
  594.                 if(nRC==2)
  595.                   SendMessage(hLbxLFiles,LB_ADDSTRING,0,(LONG)remotename);
  596.                 else
  597.                   break;
  598.                    } // end of loop
  599.                  GetLocalDirForWnd(globalhWnd);
  600.               } // end of count ok
  601.  
  602. set_busy(FALSE);
  603. EnableWindow(hBtnAbort,FALSE);
  604. return 0;
  605. }
  606.  
  607. /* ----------------------------------------------------------- */
  608.  
  609. /* zzz
  610.   instead of getting files here we need to change the local directory
  611.   to the newly created directory and then change the remote dir to
  612.   each selected dir and then do a remote list then select all items in
  613.   the files window and call remote_to_local for each
  614.   then select all items except .. in the dir window and recall this function
  615.   to recurse through that directory
  616. */
  617.  
  618. DWORD remote_to_local_mirror_fx()
  619. {
  620.   char remotedirname[256];
  621.   int count,count2, count3;
  622.   char ldirsave[_MAX_PATH];
  623.   char rdirsave[_MAX_PATH];
  624.   int nIndex,nRC;
  625.   int lselects[256];
  626.  
  627.            count=SendMessage(hLbxRDir,LB_GETSELITEMS,
  628.                                  256,(LPARAM)(int *)lselects);
  629.             if(count>0 && count!=LB_ERR)
  630.               {
  631.  
  632.                 /* Get the current working directory: */
  633.                 if (_getcwd(ldirsave, _MAX_PATH ) != NULL )
  634.                   {
  635.                   SendMessage(hTxtRDir,WM_GETTEXT,_MAX_PATH,(LONG)rdirsave);
  636.                   EnableWindow(hBtnAbort,TRUE);
  637.                   turnofflistwindows();
  638.                   for(nIndex=0;nIndex<count;nIndex++)
  639.                    {
  640.                      // skip the first one if selected as it is bogus
  641.                      if (lselects[nIndex] != 0)
  642.                        {
  643.                          SendMessage(hLbxRDir,LB_GETTEXT,lselects[nIndex],
  644.                                  (LONG)remotedirname);
  645.                          if (mkdir(remotedirname) == 0)
  646.                            {
  647.                             DoPrintf("Created local directory %s",remotedirname);
  648.                             ++totaldirscreated;
  649.                            }
  650.                             
  651.                          chdir(remotedirname);
  652.                          GetLocalDirForWnd(globalhWnd);
  653.                
  654.                   // now change the remote directory also and do a list
  655.  
  656.                   nRC=DoCWD(ctrl_socket,remotedirname);
  657.                   if(nRC==FTP_COMPLETE)
  658.                      {
  659.                        GetRemoteDirForWnd(globalhWnd);
  660.                --totalfilestransfered;
  661.  
  662.                      }
  663.                   else
  664.                    {
  665.                     DoPrintf("Aborting since remote cwd failed...");
  666.                     set_busy(FALSE);
  667.                     EnableWindow(hBtnAbort,FALSE);
  668.                     turnonlistwindows();
  669.                     return 0;
  670.                    }
  671.  
  672.              // now go through everything in the file window and get it
  673.  
  674.             count2=SendMessage(hLbxRFiles,LB_GETCOUNT,0,0);
  675.             if(count2>0 && count2!=LB_ERR)
  676.               {
  677.  
  678.                count3=SendMessage(hLbxRFiles,LB_SELITEMRANGEEX,
  679.                                  (WPARAM)0 ,(LPARAM) count2);
  680.                   if (count3 != LB_ERR)
  681.                     {
  682.                       // now that this worked ok call the function to get them
  683.                       
  684.                       set_busy(TRUE);
  685.                       remote_to_local_fx();
  686.                       set_busy(FALSE);
  687.                     }
  688.                   else
  689.                     {
  690.                     DoPrintf("Aborting since remote file selection failed...");
  691.                     set_busy(FALSE);
  692.                     EnableWindow(hBtnAbort,FALSE);
  693.                     turnonlistwindows();
  694.                     return 0;
  695.             }  
  696.               }
  697.               
  698.              // now we got all files in this directory so select all dirs
  699.              // under it and recall ourself
  700.              // then cd back to orig directory so we can continue
  701.              // with next dir at this level
  702.              // ignore first dir which is always ..
  703.  
  704.             count2=SendMessage(hLbxRDir,LB_GETCOUNT,0,0);
  705.             if(count2>1 && count2!=LB_ERR)
  706.               {
  707.  
  708.                count3=SendMessage(hLbxRDir,LB_SELITEMRANGEEX,
  709.                                  (WPARAM)1 ,(LPARAM) count2);
  710.                   if (count3 != LB_ERR)
  711.                     {
  712.                       // now that this worked ok call ourself to recurse
  713.                       remote_to_local_mirror_fx();
  714.                     }
  715.               }
  716.              
  717.             // now cd back to the original dir so we can continue
  718.             chdir(ldirsave);
  719.             GetLocalDirForWnd(globalhWnd);
  720.             nRC=DoCWD(ctrl_socket,rdirsave);
  721.             if(nRC==FTP_COMPLETE)
  722.                { 
  723.                 GetRemoteDirForWnd(globalhWnd);
  724.                 --totalfilestransfered;
  725.  
  726.                }
  727.               else
  728.                {
  729.                 DoPrintf("Aborting since remote cwd failed...");
  730.                 set_busy(FALSE);
  731.                 EnableWindow(hBtnAbort,FALSE);
  732.                 turnonlistwindows();
  733.                 return 0;
  734.                }
  735.  
  736.                } // skip bogus .. selection
  737.             // continue the loop
  738.                    } // end of loop
  739.                  } // end of getcwd ok
  740.           } // end of count ok
  741.  
  742. // print the totals
  743.   if (totalfilestransfered > 0)
  744.     { 
  745.       char str1[30];
  746.       char str2[30];
  747.  
  748.      if (totalfilestransfered == 1)
  749.       strcpy(str1,"file");
  750.       else strcpy(str1,"files");
  751.      
  752.      if (totaldirscreated == 1)
  753.        strcpy(str2,"directory");
  754.        else strcpy(str2,"directories");
  755.        
  756.      DoPrintf("%ld %s tranmitted, %ld %s created.",
  757.       totalfilestransfered,str1,totaldirscreated,str2);
  758.     } 
  759. if (totaltimefortransfer > 0)
  760.   {
  761.     DoPrintf("%ld bytes received in %.2f seconds, (%3.2fKbytes/sec).",
  762.       totalbytestransfered,(float)totaltimefortransfer,
  763.       (float)totalbytestransfered/1024.000/(float)totaltimefortransfer);
  764.   }
  765.  
  766. mirrorinprogress = FALSE;
  767. set_busy(FALSE);
  768. EnableWindow(hBtnAbort,FALSE);
  769. turnonlistwindows();
  770. return 0;
  771.  
  772. }
  773.  
  774. /* --------------------------------------------------------- */
  775.  
  776.  
  777. DWORD remote_display_fx()
  778.  
  779. {
  780.     
  781.   int nIndex,nRC;
  782.  
  783.             char tmp[300];
  784.             char remotename[80];
  785.  
  786.             if((nIndex=SendMessage(hLbxRFiles,LB_GETCURSEL,
  787.                 0,0L))!=LB_ERR)
  788.             {
  789.                  SendMessage(hLbxRFiles,LB_GETTEXT,nIndex,
  790.                                  (LONG)remotename);
  791.                  wsprintf(tmp,"RETR %s",remotename);
  792.                  EnableWindow(hBtnAbort,TRUE);
  793.                  nRC=RetrieveFile((SOCKET)ctrl_socket,(LPSTR)tmp,
  794.                            (LPSTR)szTmp1File,(LPSTR)szTmp1File,TYPE_A);
  795.                  if(nRC==2)
  796.                    {
  797.                     wsprintf(szString,"%s %s",szViewer,szTmp1File);
  798.                     if(strchr(szTmp1File,'.')==NULL)
  799.                        strcat(szString,".");
  800.                     WinExec(szString,SW_SHOW);
  801.                    }
  802.                  GetLocalDirForWnd(globalhWnd);
  803.          }
  804. set_busy(FALSE);
  805. EnableWindow(hBtnAbort,FALSE);
  806. return 0;
  807. }
  808.  
  809.  
  810.  
  811. /* ----------------------------------------------------------- */
  812. DWORD connect_fx()
  813. {
  814.     
  815.   int nRC;
  816.   
  817.   connectpending = TRUE;
  818.  
  819.           if(ctrl_socket==INVALID_SOCKET)
  820.           {
  821.              EnableWindow(hBtnConnect,FALSE);
  822.              use_gateway=0;
  823.              nRC=DialogBox(hInst,(LPSTR)"DLG_HOST",globalhWnd,WS_HostMsgProc);
  824.              if(nRC)
  825.              {
  826.               EnableWindow(hBtnAbort,TRUE);
  827.               ctrl_socket=(SOCKET)DoConnect(szRemoteHost);
  828.               if(ctrl_socket!=INVALID_SOCKET)
  829.                 {
  830.                 if(szInitDir[0]!=0)
  831.                   DoCWD(ctrl_socket,szInitDir);
  832.                 }
  833.                else // didn't connect so renable button
  834.                  EnableWindow(hBtnConnect,TRUE);
  835.  
  836.                 if(LOWORD(globalwParam)==BTN_CONNECT)
  837.                   GetRemoteDirForWnd(globalhWnd);
  838.              } // ok nrc
  839.           }
  840.             else
  841.             SendMessage(hTxtStatus,WM_SETTEXT,0,(LPARAM)"Already connected");
  842. set_busy(FALSE);
  843. connectpending = FALSE;
  844. EnableWindow(hBtnAbort,FALSE);
  845. return 0;
  846. }
  847.           
  848. /* ---------------------------------------------------------- */
  849. DWORD drop_files_fx()
  850.  
  851. {
  852.     
  853.   int nRC;
  854.  
  855.          POINT pt;
  856.          WORD cFiles, a;
  857.          char szFile[256];
  858.          char szRemoteName[256];
  859.          u_char tmp[2300];
  860.          LPSTR lpszBaseName;
  861.  
  862.          DragQueryPoint((HANDLE) globalwParam, &pt);
  863.  
  864.          cFiles = DragQueryFile((HANDLE) globalwParam, 0xFFFF, (LPSTR) NULL, 0);
  865.          if(!bConnected)
  866.            DoPrintf("NOT CONNECTED!! File(s) ignored.");
  867.          else if(bCmdInProgress)
  868.            DoPrintf("We are already busy!! File(s) ignored.");
  869.          else
  870.            {
  871.            for(a = 0; a < cFiles; pt.y += 20, a++)
  872.             {
  873.              DragQueryFile((HANDLE) globalwParam, a, szFile, sizeof(szFile));
  874.              MakeLower(szFile);
  875.              if((lpszBaseName=strrchr(szFile,'\\'))!=NULL)
  876.               {
  877.                lstrcpy(szRemoteName,++lpszBaseName);
  878.                if(bInteractive) 
  879.                   StdInput(szRemoteName,"Enter remote file name for %s:",lpszBaseName);
  880.                EnableWindow(hBtnAbort,TRUE);
  881.                wsprintf(tmp,"sending %s as %s (%u of %u)",szFile,szRemoteName,a,cFiles);
  882.                SendMessage(hTxtStatus,WM_SETTEXT,0,(LPARAM)tmp);
  883.                wsprintf(tmp,"STOR %s",szRemoteName);
  884.                nRC=SendFile(ctrl_socket,tmp,szFile,fType);
  885.                if(nRC!=2) break;
  886.               }
  887.             } // end of loop
  888.            GetRemoteDirForWnd(globalhWnd);
  889.            } // end ok case
  890.          DragFinish((HANDLE) globalwParam);
  891.  
  892. set_busy(FALSE);
  893. EnableWindow(hBtnAbort,FALSE);
  894. return 0;
  895. }
  896.  
  897. /* -------------------------------------------- */
  898.       
  899. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  900.                    LPSTR lpszCmdLine, int nCmdShow)
  901. {
  902.   MSG        msg;
  903.   int        nRc;
  904.   long       nWndunits;
  905.   int        nX;
  906.   int        nY;
  907.   int        nWidth;
  908.   int        nHeight;
  909.   int        err;
  910. //  HINSTANCE hWinSock;
  911.  
  912.   InitializeCriticalSection(&busy_variable);
  913.  
  914.   if (strstr(lpszCmdLine,"-d") != NULL)
  915.     {
  916.       // we want debugging
  917.       DEBUGGING_ON = TRUE;
  918.     }
  919.    
  920.   if ((err = WSAStartup((WORD)0x0101, &WSAData))!=0)  // register task with
  921.   {                                         // winsock tcp/ip API
  922.     MessageBox(NULL,ReturnWSError(err,NULL),"WS_FTP - WSAStartup",
  923.           MB_OK|MB_ICONEXCLAMATION);
  924.   } else {
  925.     strcpy(szAppName, "WS_FTP");
  926.     hInst = hInstance;
  927.  
  928.     if(!hPrevInstance)
  929.     {
  930.       // register window classes if first instance of application
  931.       if ((nRc = nCwRegisterClasses()) == -1)
  932.       {
  933.         // registering one of the windows failed
  934.         MessageBox((HWND)NULL, "Window creation failed",
  935.               NULL, MB_ICONEXCLAMATION);
  936.         return nRc;    
  937.       }
  938.     }
  939.  
  940.     // Create a device independant size and location
  941.     nWndunits = GetDialogBaseUnits();
  942.     nWndx = LOWORD(nWndunits);
  943.     nWndy = HIWORD(nWndunits);
  944.     nX = ((18 * nWndx) / 4);
  945.     nY = ((18 * nWndy) / 8);
  946.     nWidth = ((247 * nWndx) / 4);
  947.     nHeight = ((211 * nWndy) / 8);
  948.  
  949.     // create application's Main window
  950.     hWndMain = CreateWindow(
  951.       szAppName, "WinSock_FTP",
  952.       WS_CAPTION     | WS_SYSMENU    | WS_MINIMIZEBOX  |
  953.       WS_CLIPCHILDREN | WS_OVERLAPPED,
  954.       nX,nY, nWidth, nHeight,
  955.       (HWND)NULL, (HMENU)NULL, hInst,  NULL);
  956.  
  957.     if(hWndMain == (HWND)NULL)
  958.     {
  959.       MessageBox((HWND)NULL, "Error registering class",
  960.             NULL, MB_ICONEXCLAMATION);
  961.       return 2;
  962.     }
  963.  
  964.     ShowWindow(hWndMain, nCmdShow);         // display main window
  965.     GetLocalInfo();
  966.     if(bAutoStart)
  967.       PostMessage(hWndMain,WM_COMMAND,BTN_CONNECT,0L);
  968.  
  969.       // lgk now check if command line stuff
  970.       if (check_command_line() == 1)
  971.        { 
  972.        // use to exit here when not multi-threaded but now returns immediately
  973.        }
  974.         
  975.  
  976.     while(GetMessage(&msg, (HWND)NULL, 0, 0))     // Until WM_QUIT message
  977.     {
  978.     // lgk add extra code to check for carriage return in our dir boxes
  979.       if (msg.message == WM_KEYDOWN     &&
  980.           msg.wParam == VK_RETURN)
  981.           // ok we have it now do it
  982.         {
  983.         
  984.          if (msg.hwnd == hLdirBox)
  985.          {
  986.            GetLocalDirForWnd(msg.hwnd);
  987.          }
  988.          else
  989.           if (msg.hwnd == hRdirBox)
  990.              {
  991.            if (check_busy())
  992.                DoPrintf("Currently Busy with another remote operation ...\n");
  993.             else
  994.               {
  995.                 globalhWnd = msg.hwnd;
  996.                 globalwParam = msg.wParam;
  997.                 set_busy(TRUE);
  998.                // create thread and start remote list fx
  999.                 threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_list_fx,NULL,0,&threadid);
  1000.               }               
  1001.           }
  1002.    
  1003.       }
  1004.       
  1005.       TranslateMessage(&msg);
  1006.       DispatchMessage(&msg);
  1007.     }
  1008.     WSACleanup();
  1009.     ReleaseDisplayMem();
  1010.  
  1011.     // Do clean up before exiting from the application
  1012.     CwUnRegisterClasses();
  1013.   }
  1014.   return msg.wParam;
  1015. } //  End of WinMain
  1016.  
  1017.  
  1018. int StdInput(LPSTR dest,LPSTR fmt,...)
  1019. {
  1020.   va_list args;
  1021. //  FARPROC lpfnMsgProc;
  1022.   int  iRetCode;
  1023.  
  1024.   va_start(args,fmt);
  1025.   vsprintf(szDlgPrompt,fmt,args);
  1026.   va_end(args);
  1027.   if (dest != NULL) // lgk fix for nt caused access violation
  1028.    lstrcpy(szDlgEdit,dest);
  1029.   
  1030.   else szDlgEdit[0] = 0;
  1031.  
  1032. //  lpfnMsgProc=MakeProcInstance((FARPROC)WS_InputMsgProc,hInst);
  1033.     iRetCode=DialogBox(hInst,(LPSTR)"DLG_INPUT",hWndMain,WS_InputMsgProc);
  1034. //  FreeProcInstance(lpfnMsgProc);
  1035.   if(iRetCode && dest) 
  1036.   
  1037.   // lgk fix here since if dest was null we cannot copy to it
  1038.    if (dest != NULL)
  1039.     lstrcpy(dest,szDlgEdit);
  1040.   
  1041.   return(iRetCode);
  1042. }
  1043.  
  1044. int StdInputPassword(LPSTR dest,LPSTR fmt,...)
  1045. {
  1046.   va_list args;
  1047.   //FARPROC lpfnMsgProc;
  1048.   int  iRetCode;
  1049.  
  1050.   va_start(args,fmt);
  1051.   vsprintf(szDlgPrompt,fmt,args);
  1052.   va_end(args);
  1053.   lstrcpy(szDlgEdit,dest);
  1054. //  lpfnMsgProc=MakeProcInstance((FARPROC)WS_InputMsgProc,hInst);
  1055.   iRetCode=DialogBox(hInst,(LPSTR)"DLG_INPUT_PASSWORD",hWndMain,WS_InputMsgProc);
  1056. //  FreeProcInstance(lpfnMsgProc);
  1057.   if(iRetCode && dest) lstrcpy(dest,szDlgEdit);
  1058.   return(iRetCode);
  1059. }
  1060.  
  1061. /************************************************************************/
  1062. /* Main Window Procedure                                                */
  1063. /************************************************************************/
  1064. LRESULT CALLBACK WndProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
  1065. {
  1066.   int nIndex; //,nRC;
  1067.   char tempdirectoryname[256];
  1068.  
  1069.  
  1070.   switch (Message)
  1071.   {
  1072.     
  1073.     case WM_COMMAND:
  1074.       if(LOWORD(wParam)==BTN_CLOSE || LOWORD(wParam)==BTN_EXIT ||
  1075.          LOWORD(wParam)==CMD_CLOSE || LOWORD(wParam)==IDM_EXIT)
  1076.         {
  1077.         BOOLEAN rfile = FALSE;
  1078.         BOOLEAN sfile = FALSE;
  1079.         bAborted=TRUE;
  1080.  
  1081.             // kill remote thread first 
  1082.             if (check_busy())
  1083.             {
  1084.              DoAddLine("Aborting thread before closing/exiting\n");
  1085.              TerminateThread(threadhandle,1);
  1086.              mirrorinprogress = FALSE;
  1087.              turnonlistwindows();
  1088.              set_busy(FALSE);
  1089.              bCmdInProgress = 0;
  1090.  
  1091.             }
  1092.        
  1093.        if(data_socket!=INVALID_SOCKET)
  1094.           {
  1095.             // DWORD waitval = 0;
  1096.                int tid = 0;
  1097.                   data_socket=DoClose(data_socket);
  1098.                   // now wait for the abort message
  1099.                   DoPrintf("Waiting for Abort Response message. (550)\n");
  1100.                   // create thread and start remote list fx
  1101.               // threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)waitfor550,NULL,0,&threadid);
  1102.                   aborttimerexpired = FALSE;
  1103.                   SetTimer(hWnd,21,15000,(TIMERPROC)myaborttimerproc);
  1104.                   waitfor550((SOCKET)ctrl_socket);
  1105.                   KillTimer(hWnd,21);
  1106.  
  1107.                 //  waitval = WaitForSingleObject(threadhandle,15000);
  1108.                   // wait 15 seconds if this fails terminate the thread
  1109.  
  1110.                 /*  if (waitval == WAIT_TIMEOUT)
  1111.                    {
  1112.                     DoPrintf("Abort Timeout has Expired\n");
  1113.                     DoPrintf("Abort Failed... Recommend you close/reconnect\n");
  1114.                     TerminateThread(threadhandle,1);
  1115.                     mirrorinprogress = FALSE;
  1116.                     turnonlistwindows();
  1117.                     set_busy(FALSE);
  1118.                     bCmdInProgress = 0;
  1119.                    } */
  1120.  
  1121.              // now check if files were open and close them
  1122.              closefilesonabort(&rfile,&sfile);
  1123.           }
  1124.  
  1125.                  bAborted=TRUE;
  1126.              bCmdInProgress = 0;
  1127.  
  1128.  
  1129.         if(listen_socket!=INVALID_SOCKET)
  1130.           listen_socket=DoClose(listen_socket);
  1131.         if(ctrl_socket!=INVALID_SOCKET)
  1132.          {
  1133.           command(ctrl_socket,"QUIT");
  1134.           ctrl_socket=DoClose(ctrl_socket);
  1135.           bConnected=FALSE;
  1136.         }
  1137.  
  1138.         bCmdInProgress = 0;
  1139.         SetWindowText(hWnd,"WS_FTP32");
  1140.         if(LOWORD(wParam)==IDM_EXIT || LOWORD(wParam)==BTN_EXIT)
  1141.           SendMessage(hWnd,WM_CLOSE,0,0L);
  1142.         else
  1143.           { // close not exit so enable windows correctly
  1144.             EnableWindow(hBtnConnect,TRUE);
  1145.             EnableWindow(hBtnAbort,FALSE);
  1146.             EnableWindow(hBtnClose,FALSE);
  1147.             GetRemoteDirForWnd(hWnd);
  1148.           }
  1149.        // if we are closing we still need to close files that were open or if we
  1150.        // were receiving we need to update display
  1151.        // we don't care about remote since this is updated anyway
  1152.        if (rfile)
  1153.         GetLocalDirForWnd(hWnd);
  1154.           
  1155.         break;
  1156.         } //else if ((bCmdInProgress)  return(FALSE);
  1157.  
  1158.       switch (LOWORD(wParam))
  1159.       {
  1160.  
  1161. // child windows messages ************************************
  1162. // local buttons and boxes
  1163.  
  1164. // lgk new case for abort
  1165.            case BTN_ABORT:
  1166.  
  1167.           // kill remote thread first 
  1168.           // problem here if we abort during a connect we also need to close the control socket
  1169.           // check this via the connect flag
  1170.   
  1171.            // since we cant get this to work correctly disable it for now
  1172.          //  DoPrintf("Abort is Not Yet Implemented Due to problems.\n");
  1173.          
  1174.           if (check_busy())
  1175.             {
  1176.              BOOLEAN rfile = FALSE;
  1177.              BOOLEAN sfile = FALSE;
  1178.              
  1179.              DoPrintf("Aborting Remote thread\n");
  1180.              DoPrintf("WARNING: If the abort fails you may have to close/exit");
  1181.              TerminateThread(threadhandle,1);
  1182.              mirrorinprogress = FALSE;
  1183.              turnonlistwindows();
  1184.              set_busy(FALSE);
  1185.        
  1186.              if(data_socket!=INVALID_SOCKET)
  1187.                 {
  1188.                  //DWORD waitval = 0;
  1189.                  int tid = 0;
  1190.  
  1191.                 //  shutdown(data_socket,2);
  1192.                   data_socket=DoClose((SOCKET)data_socket);
  1193.                   // now wait for the abort message
  1194.                   DoPrintf("Waiting for Abort Response message. (550)\n");
  1195.                 // create thread and start remote list fx
  1196.             //     threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)waitfor550,(LPVOID)ctrl_socket,0,&threadid);
  1197.            //     myctrlsocket = (SOCKET)ctrl_socket;
  1198.                   aborttimerexpired = FALSE;
  1199.                   SetTimer(hWnd,21,15000,(TIMERPROC)myaborttimerproc);
  1200.                   waitfor550((SOCKET)ctrl_socket);
  1201.                   KillTimer(hWnd,21);
  1202.              //     waitval = WaitForSingleObject(threadhandle,20000);
  1203.                   // wait 20 seconds if this fails terminate the thread
  1204.  
  1205.                    // ok now close any open files
  1206.                    closefilesonabort(&rfile,&sfile);
  1207.                    
  1208.                  }
  1209.              bAborted=TRUE;
  1210.              bCmdInProgress = 0;
  1211.  
  1212.              if(listen_socket!=INVALID_SOCKET)
  1213.                listen_socket=DoClose((SOCKET)listen_socket);
  1214.              
  1215.                 bCmdInProgress = 0;
  1216.               
  1217.               if (connectpending)
  1218.               {
  1219.                 int err = 0;
  1220.                 if (ctrl_socket!=INVALID_SOCKET)
  1221.                   {
  1222.                     
  1223.                     command((SOCKET)ctrl_socket,"QUIT");
  1224.                     ctrl_socket = DoClose((SOCKET)ctrl_socket);
  1225.                   }
  1226.                     bConnected = FALSE;
  1227.                     DoPrintf("Remote Connect Aborted\n");
  1228.                     connectpending = FALSE;
  1229.                     bCmdInProgress = 0;
  1230.                     EnableWindow(hBtnConnect,TRUE);
  1231.                     EnableWindow(hBtnAbort,FALSE);
  1232.                     EnableWindow(hBtnClose,FALSE);
  1233.                     SetWindowText(hWnd,"WS_FTP32");
  1234.                     iCode = 0;
  1235.  
  1236.                 
  1237.               } 
  1238.               else
  1239.                         {
  1240.                           DoPrintf("Remote Operation Aborted\n");
  1241.                           // only do this if no connect pending
  1242.                           if (sfile)
  1243.                             GetRemoteDirForWnd(hWnd);
  1244.                         }
  1245.    
  1246.                     // now if we were sending or receiving a file update the windows accordingly
  1247.                      if (rfile)
  1248.                       GetLocalDirForWnd(hWnd);
  1249.             }    
  1250.         break;
  1251.  
  1252.  
  1253.        // lgk new case for changing txt in directory search routine
  1254.            case TXT_LDIRSEL:
  1255.          {
  1256.           // check if carriage return
  1257.           char *temp = localsearchstring();
  1258.           if ((HIWORD(wParam) == EN_KILLFOCUS) && SendMessage(hLdirBox,EM_GETMODIFY,0,0))
  1259.            {
  1260.              GetLocalDirForWnd(hWnd);
  1261.            }
  1262.            // bug in redraw so force it
  1263.           if (HIWORD(wParam) == EN_UPDATE)
  1264.              {
  1265.               SendMessage(hLdirBox,WM_SETFONT,0,MAKELPARAM(TRUE,0));
  1266.               }
  1267.  
  1268.           }    
  1269.         break;
  1270.  
  1271.         case LST_LDIRS:
  1272.           if (HIWORD(wParam) !=LBN_DBLCLK) return(FALSE);
  1273.         case BTN_LCHANGE:
  1274.           {
  1275.             int count = SendMessage(hLbxLDir,LB_GETSELCOUNT,
  1276.                 0,0L);
  1277.             int count2 = 0;
  1278.             
  1279.             if (count > 1)
  1280.               {
  1281.                 DoPrintf("Only 1 directory can be selected for the chdir operation.");
  1282.               }  
  1283.             else if (count == 0)
  1284.              { // ok case so ask
  1285.               if(StdInput(NULL,"Enter local directory name:")) {
  1286.                 if(szDlgEdit[1]==':')
  1287. #ifdef _MSC_
  1288.                   _chdrive(tolower(szDlgEdit[0])-0x60);
  1289. #else
  1290.                   setdisk(tolower(szDlgEdit[0])-'a');
  1291. #endif
  1292.                 chdir(szDlgEdit);
  1293.                 GetLocalDirForWnd(hWnd);
  1294.               }
  1295.              }
  1296.            else // (count == 1)
  1297.              {
  1298.             count2=SendMessage(hLbxLDir,
  1299.                       LB_GETSELITEMS,256,(LPARAM)(int far *)selects);
  1300.               nIndex = selects[0];
  1301.               SendMessage(hLbxLDir,LB_GETTEXT,nIndex,
  1302.                                  (LONG)szMsgBuf2);
  1303.               if(strncmp(szMsgBuf2,"[-",2)==0) {
  1304. #ifdef _MSC_
  1305.                 _chdrive(tolower(szMsgBuf2[2])-0x60);
  1306. #else
  1307.                 setdisk(szMsgBuf2[2]-'a');
  1308. #endif
  1309.                 GetLocalDirForWnd(hWnd);
  1310.               } else if(chdir(szMsgBuf2)==0)
  1311.                 GetLocalDirForWnd(hWnd);
  1312.              }
  1313.           }
  1314.           break;
  1315.         case LST_LFILES:
  1316.           if(HIWORD(wParam) !=LBN_DBLCLK) return(FALSE);
  1317.         case BTN_LOCAL_TO_REMOTE:
  1318.           {
  1319.             globalhWnd = hWnd;
  1320.             globalwParam = wParam;
  1321.             // lgk new code first check if busy and if so print out a message
  1322.             if (check_busy())
  1323.                DoPrintf("Currently Busy with another remote operation ...\n");
  1324.             else
  1325.               {
  1326.                globalhWnd = hWnd;
  1327.                globalwParam = wParam;
  1328.                 set_busy(TRUE);
  1329.  
  1330.                   {
  1331.                  int dircount,filecount = 0;
  1332.                    
  1333.                  filecount =  SendMessage(hLbxLFiles,LB_GETSELCOUNT,0,0);
  1334.                  dircount = SendMessage(hLbxLDir,LB_GETSELCOUNT,0,0);
  1335.                  if ((dircount > 0) && (filecount == 0))
  1336.                    {
  1337.                     mirrorinprogress = TRUE;
  1338.             totalbytestransfered = 0L;
  1339.                     totaltimefortransfer = 0L;
  1340.                     totalfilestransfered = 0;
  1341.                     totaldirscreated = 0;
  1342.  
  1343.                      // create thread and start remote to local fx
  1344.                     threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)local_to_remote_mirror_fx,NULL,0,&threadid);
  1345.  
  1346.                    }
  1347.                 else
  1348.                 {
  1349.               
  1350.                // create and call button to remote thread here
  1351.                threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)local_to_remote_fx,NULL,0,&threadid);
  1352.             }
  1353.               }
  1354.               } // end of not busy
  1355.           } // end of btn local to remote
  1356.           break;
  1357.  
  1358.           // lgk allow local commands while remote are running
  1359.  
  1360.           
  1361.         case BTN_LMKDIR:
  1362.           if(StdInput(NULL,"Enter new local directory name:")) {
  1363.             mkdir(szDlgEdit);
  1364.             GetLocalDirForWnd(hWnd);
  1365.           }
  1366.           break;
  1367.         case BTN_LRMDIR:
  1368.             if((nIndex=SendMessage(hLbxLDir,LB_GETCURSEL,
  1369.                 0,0L))!=LB_ERR)
  1370.             {
  1371.               SendMessage(hLbxLDir,LB_GETTEXT,nIndex,
  1372.                                  (LONG)szMsgBuf2);
  1373.               if(VerifyDelete(szMsgBuf2))
  1374.                 if(rmdir(szMsgBuf2)==0)
  1375.                   GetLocalDirForWnd(hWnd);
  1376.             }
  1377.           break;
  1378.         case BTN_LDELETE:
  1379.           {
  1380.             int count;
  1381.             count=SendMessage(hLbxLFiles,
  1382.                       LB_GETSELITEMS,256,(LPARAM)(int far *)selects);
  1383.             if(count>0 && count!=LB_ERR) {
  1384.               for(nIndex=0;nIndex<count;nIndex++) {
  1385.                 SendMessage(hLbxLFiles,LB_GETTEXT,selects[nIndex],
  1386.                                  (LONG)szDlgEdit);
  1387.                 if(VerifyDelete(szDlgEdit))
  1388.                   unlink(szDlgEdit);
  1389.               }  
  1390.               GetLocalDirForWnd(hWnd);
  1391.             }
  1392.           }
  1393.           break;
  1394.         case BTN_LRENAME:
  1395.           if((nIndex=SendMessage(hLbxLFiles,LB_GETCURSEL,
  1396.                 0,0L))!=LB_ERR)
  1397.           {
  1398.             SendMessage(hLbxLFiles,LB_GETTEXT,nIndex,
  1399.                                (LONG)szMsgBuf2);
  1400.             if(StdInput(NULL,"Enter new name for \"%s\":",szMsgBuf2))
  1401.               if(rename(szMsgBuf2,szDlgEdit)==0)
  1402.                 GetLocalDirForWnd(hWnd);
  1403.           }
  1404.           break;
  1405.         case BTN_LDISPLAY:
  1406.           {
  1407.             char remotename[80];
  1408.             if((nIndex=SendMessage(hLbxLFiles,LB_GETCURSEL,
  1409.                 0,0L))!=LB_ERR)
  1410.             {
  1411.               SendMessage(hLbxLFiles,LB_GETTEXT,nIndex,
  1412.                                  (LONG)remotename);
  1413.               wsprintf(szMsgBuf2,"%s %s",szViewer,remotename);
  1414.               if(strchr(remotename,'.')==NULL)
  1415.                 strcat(szMsgBuf2,".");
  1416.               WinExec(szMsgBuf2,SW_SHOW);
  1417.             }
  1418.           }
  1419.           break;
  1420.  
  1421.          // remote buttons and boxes
  1422.         case BTN_RMKDIR:
  1423.            // lgk new code first check if busy and if so print out a message
  1424.             if (check_busy())
  1425.                DoPrintf("Currently Busy with another remote operation ...\n");
  1426.             else
  1427.               {
  1428.                globalhWnd = hWnd;
  1429.                globalwParam = wParam;
  1430.                set_busy(TRUE);
  1431.                threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_mkdir_fx,NULL,0,&threadid);
  1432.                // create thread and start remote makedir fx
  1433.           }               
  1434.           break;
  1435.           
  1436.         case BTN_RRMDIR:
  1437.             // lgk new code first check if busy and if so print out a message
  1438.             if (check_busy())
  1439.                DoPrintf("Currently Busy with another remote operation ...\n");
  1440.             else
  1441.               {
  1442.                 globalhWnd = hWnd;
  1443.                 globalwParam = wParam;
  1444.                 set_busy(TRUE);
  1445.                // create thread and start remote remove dir fx
  1446.                 threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_rmdir_fx,NULL,0,&threadid);
  1447.           }               
  1448.           break;
  1449.  
  1450.         case BTN_RDELETE:
  1451.             // lgk new code first check if busy and if so print out a message
  1452.             if (check_busy())
  1453.                DoPrintf("Currently Busy with another remote operation ...\n");
  1454.             else
  1455.               {
  1456.                globalhWnd = hWnd;
  1457.                globalwParam = wParam;
  1458.                set_busy(TRUE);
  1459.                // create thread and start remote delete fx
  1460.                threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_delete_fx,NULL,0,&threadid);
  1461.           }               
  1462.           break;
  1463.  
  1464.           
  1465.         case BTN_RRENAME:
  1466.           // lgk new code first check if busy and if so print out a message
  1467.            if (check_busy())
  1468.                DoPrintf("Currently Busy with another remote operation ...\n");
  1469.             else
  1470.               {
  1471.                 globalhWnd = hWnd;
  1472.                 globalwParam = wParam;
  1473.                  set_busy(TRUE);
  1474.                // create thread and start remote rename fx
  1475.                threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_rename_fx,NULL,0,&threadid);
  1476.           }               
  1477.           break;
  1478.  
  1479.         // lgk new case for changing txt in directory search routine
  1480.            case TXT_RDIRSEL:
  1481.            // bug in redraw so force it
  1482.           if (HIWORD(wParam) == EN_UPDATE)
  1483.              {
  1484.               SendMessage(hRdirBox,WM_SETFONT,0,MAKELPARAM(TRUE,0));
  1485.               }
  1486.           if ((HIWORD(wParam) == EN_KILLFOCUS) && SendMessage(hRdirBox,EM_GETMODIFY,0,0))
  1487.             // lgk new code first check if busy and if so print out a message
  1488.             if (check_busy())
  1489.                DoPrintf("Currently Busy with another remote operation ...\n");
  1490.             else
  1491.               {
  1492.                 globalhWnd = hWnd;
  1493.                 globalwParam = wParam;
  1494.                 set_busy(TRUE);
  1495.                // create thread and start remote list fx
  1496.                 threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_list_fx,NULL,0,&threadid);
  1497.           }               
  1498.           break;
  1499.        
  1500.    
  1501.         case LST_RDIRS:
  1502.          if (HIWORD(wParam) == LBN_SELCANCEL)
  1503.            {
  1504.             // turn off the item
  1505.             DoPrintf("Selection cancled.");
  1506.            }
  1507.             
  1508.           else if(HIWORD(wParam)!=LBN_DBLCLK) return(FALSE);
  1509.         case BTN_RCHANGE:
  1510.             // lgk new code first check if busy and if so print out a message
  1511.             if (check_busy())
  1512.                DoPrintf("Currently Busy with another remote operation ...\n");
  1513.             else
  1514.               {
  1515.                 globalhWnd = hWnd;
  1516.                 globalwParam = wParam;
  1517.                 set_busy(TRUE);
  1518.                // create thread and start remote cwd fx
  1519.                 threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_cwd_fx,NULL,0,&threadid);
  1520.           }               
  1521.           break;
  1522.           
  1523.         case LST_RFILES:
  1524.           if(HIWORD(wParam)!=LBN_DBLCLK) return(FALSE);
  1525.         case BTN_REMOTE_TO_LOCAL:
  1526.  
  1527.  
  1528.             // lgk new code first check if busy and if so print out a message
  1529.             if (check_busy())
  1530.                DoPrintf("Currently Busy with another remote operation ...\n");
  1531.             else
  1532.               {
  1533.                 globalhWnd = hWnd;
  1534.                 globalwParam = wParam;
  1535.                set_busy(TRUE);
  1536.  
  1537.                // if no files selected and some directories selected
  1538.                 {
  1539.                  int dircount,filecount = 0;
  1540.                    
  1541.                  filecount =  SendMessage(hLbxRFiles,LB_GETSELCOUNT,0,0);
  1542.                  dircount = SendMessage(hLbxRDir,LB_GETSELCOUNT,0,0);
  1543.                  if ((dircount > 0) && (filecount == 0))
  1544.                    {
  1545.                     mirrorinprogress = TRUE;
  1546.                     totalbytestransfered = 0L;
  1547.                     totaltimefortransfer = 0L;
  1548.                     totalfilestransfered = 0;
  1549.                     totaldirscreated = 0;
  1550.  
  1551.                      // create thread and start remote to local fx
  1552.                     threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_to_local_mirror_fx,NULL,0,&threadid);
  1553.  
  1554.                    }
  1555.                 else
  1556.                 {
  1557.                // create thread and start remote to local fx
  1558.                threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_to_local_fx,NULL,0,&threadid);
  1559.             }
  1560.         }
  1561.           }             
  1562.           break;
  1563.  
  1564.           
  1565.         case BTN_RDISPLAY:
  1566.             // lgk new code first check if busy and if so print out a message
  1567.             if (check_busy())
  1568.                DoPrintf("Currently Busy with another remote operation ...\n");
  1569.             else
  1570.               {
  1571.                globalhWnd = hWnd;
  1572.                globalwParam = wParam;
  1573.                 set_busy(TRUE);
  1574.                // create thread and start remote display fx
  1575.                   threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)remote_display_fx,NULL,0,&threadid);
  1576.           }               
  1577.           break;
  1578.  
  1579.         case RB_ASCII:
  1580.           fType=TYPE_A;
  1581. ShowType:
  1582.         case RB_SHOWCHECKS:
  1583.           SendMessage(hRBascii, BM_SETCHECK,fType==TYPE_A,0L);
  1584.           SendMessage(hRBbinary,BM_SETCHECK,fType==TYPE_I,0L);
  1585.           SendMessage(hRBl8,    BM_SETCHECK,fType==TYPE_L,0L);
  1586.           break;
  1587.         case RB_BINARY:
  1588.           fType=TYPE_I;
  1589.           goto ShowType;
  1590.         case RB_L8:
  1591.           fType=TYPE_L;
  1592.           goto ShowType;
  1593.  
  1594. // end of child window message processing *******************
  1595.  
  1596.         case BTN_CONNECT:
  1597.         case CMD_CONNECT:
  1598.             // lgk new code first check if busy and if so print out a message
  1599.             if (check_busy())
  1600.                DoPrintf("Currently Busy with another remote operation ...\n");
  1601.             else
  1602.               {
  1603.                globalhWnd = hWnd;
  1604.                globalwParam = wParam;
  1605.                set_busy(TRUE);
  1606.                // create thread and start connect fx
  1607.                threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)connect_fx,NULL,0,&threadid);
  1608.           }               
  1609.           break;
  1610.  
  1611.         case BTN_LONG:
  1612.           if(bConnected) {
  1613.             wsprintf(szMsgBuf2,"%s %s",szViewer,szTmpFile);
  1614.             WinExec(szMsgBuf2,SW_SHOW);
  1615.           }
  1616.           break;
  1617.  
  1618.         case BTN_OPTION:
  1619.           {
  1620.            //FARPROC lpfnMsgProc;
  1621.     //        lpfnMsgProc = MakeProcInstance((FARPROC)WS_StatMsgProc, hInst);
  1622.             DialogBox(hInst, (LPSTR)"DLG_STATUS", hWnd, WS_StatMsgProc);
  1623.        //     FreeProcInstance(lpfnMsgProc);
  1624.           }
  1625.           SendMessage(hWnd,WM_COMMAND,RB_SHOWCHECKS,0l);
  1626.           break;
  1627.  
  1628.         case BTN_ABOUT:
  1629.         case IDM_ABOUT:
  1630.           { 
  1631.             DialogBox(hInst, (LPSTR)"DLG_ABOUT", hWnd, WS_AboutMsgProc);
  1632.           }
  1633.           break;
  1634.  
  1635.         default:
  1636.           if(!SubProcessAsync(hWnd,Message,wParam,lParam))
  1637.             return DefWindowProc(hWnd, Message, wParam, lParam);
  1638.       }
  1639.       break;
  1640.  
  1641.     case WM_VSCROLL:
  1642.       switch(LOWORD(wParam)) {
  1643.         case SB_LINEUP:
  1644.           ScrollStatus(-1);
  1645.           break;
  1646.         case SB_LINEDOWN:
  1647.           ScrollStatus(1);
  1648.           break;
  1649.       }
  1650.       break;
  1651.  
  1652.     case WM_CREATE:
  1653.       hStdCursor=LoadCursor((HINSTANCE)NULL,IDC_ARROW);
  1654.       hWaitCursor=LoadCursor((HINSTANCE)NULL,IDC_APPSTARTING);
  1655.       LoadUserInfo();
  1656.       hbrGray1= CreateSolidBrush(RGB(192,192,192));
  1657.       hbrGray2=CreateSolidBrush(RGB(128,128,128)); 
  1658.       hbrWhite=CreateSolidBrush(RGB(255,255,255));
  1659.     
  1660.       if (DEBUGGING_ON)
  1661.         CreateDebugWindow(hWnd,hInst);
  1662.       
  1663.       CreateSubWindows(hWnd,hInst);
  1664.       SendMessage(hLdirBox,EM_LIMITTEXT,(WPARAM)50,0);
  1665.       SendMessage(hRdirBox,EM_LIMITTEXT,(WPARAM)50,0);
  1666.       SendMessage(hLdirBox,WM_SETTEXT,0,(LPARAM)"");
  1667.       SendMessage(hRdirBox,WM_SETTEXT,0,(LPARAM)"");
  1668.       SendMessage(hLdirBox,EM_GETMODIFY,0,0);
  1669.       SendMessage(hRdirBox,EM_GETMODIFY,0,0);     
  1670.       SendMessage(hLdirBox,EM_FMTLINES,(WPARAM)1,0);     
  1671.       SendMessage(hRdirBox,EM_FMTLINES,(WPARAM)1,0);     
  1672.       GetLocalDirForWnd(hWnd);
  1673.       GetRemoteDirForWnd(hWnd);
  1674.       SendMessage(hWnd,WM_COMMAND,RB_SHOWCHECKS,0L);
  1675.       GetCurrentDirectory(140,tempdirectoryname);
  1676.       GetTempFileName(tempdirectoryname,"DIR",0,szTmpFile);
  1677.       GetTempFileName(tempdirectoryname,"DSP",0,szTmp1File);
  1678.       DragAcceptFiles(hWnd,TRUE);
  1679.       // lgk limit the text for both dir boxes and initialize them to blank
  1680.  
  1681.         break;
  1682.   // lgk timer messages do not work between threads so use a timer proc now
  1683.  
  1684.     case WM_TIMER:
  1685.     if(wParam==10)
  1686.         {
  1687.         KillTimer(hWndMain,10);
  1688.         if(WSAIsBlocking())
  1689.          {
  1690.             // lgk if we are blocking in another thread here we need to kill
  1691.             // it also
  1692.            if (check_busy())
  1693.             {
  1694.              DoAddLine("Timer cancelled blocking call");    
  1695.              bAborted=TRUE;
  1696.              WSACancelBlockingCall();
  1697.              TerminateThread(threadhandle,1);
  1698.              mirrorinprogress = FALSE;
  1699.              turnonlistwindows();
  1700.              set_busy(FALSE);
  1701.             }
  1702.          else
  1703.          {
  1704.           DoAddLine("Timer cancelled blocking call");    
  1705.           bAborted=TRUE;
  1706.           WSACancelBlockingCall();
  1707.      }
  1708.      }         
  1709.         }
  1710.       break;
  1711.  
  1712.  
  1713.      case WM_CTLCOLORBTN:
  1714.            if(LOWORD(lParam)<10) return((LRESULT)NULL);
  1715.  // lgk add suport for background color change for our edit box
  1716.      case WM_CTLCOLORSTATIC:
  1717.                SelectObject((HDC)wParam, GetStockObject(ANSI_VAR_FONT));
  1718.                 SetBkColor((HDC) wParam, RGB(192,192,192));
  1719.                 return(LRESULT)hbrGray1;
  1720.                 break;
  1721.  
  1722.      case WM_CTLCOLOREDIT:
  1723.                SelectObject((HDC)wParam, GetStockObject(ANSI_VAR_FONT));
  1724.                 SetBkColor((HDC) wParam, RGB(255, 255, 255));
  1725.                 return(LRESULT)hbrWhite;
  1726.                 break;
  1727.         
  1728.  
  1729.     case WM_SETCURSOR:
  1730.       if(bCmdInProgress) {
  1731.         SetCursor(hWaitCursor);
  1732.         return(TRUE);
  1733.       } else
  1734.         return DefWindowProc(hWnd, Message, wParam, lParam);
  1735.  
  1736.     case WM_DROPFILES:
  1737.             // lgk new code first check if busy and if so print out a message
  1738.             if (check_busy())
  1739.                DoPrintf("Currently Busy with another remote operation ...\n");
  1740.             else
  1741.               {
  1742.                globalhWnd = hWnd;
  1743.                globalwParam = wParam;
  1744.                 set_busy(TRUE);
  1745.                // create thread and start dropfiles fx
  1746.                threadhandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)drop_files_fx,NULL,0,&threadid);
  1747.           }               
  1748.           break;
  1749.  
  1750.     case WM_PAINT:  // code for the window's client area
  1751.       DoMainPaint(hWnd);
  1752.       break;
  1753.  
  1754.     case WM_CLOSE:  // close the window 
  1755.       // Destroy child windows, modeless dialogs, then, this window
  1756.       if (hWnd == hWndMain) {
  1757.         if(data_socket!=INVALID_SOCKET)
  1758.           data_socket=DoClose(data_socket);
  1759.         if(listen_socket!=INVALID_SOCKET)
  1760.           listen_socket=DoClose(data_socket);
  1761.         if(ctrl_socket!=INVALID_SOCKET)
  1762.           ctrl_socket=DoClose(ctrl_socket);
  1763.         DestroyWindow(hWnd);
  1764.         SaveUserInfo();
  1765.         DeleteObject(hbrGray1);
  1766.         DeleteObject(hbrGray2);
  1767.         DeleteObject(hbrWhite);
  1768.         _unlink(szTmpFile);
  1769.         _unlink(szTmp1File);
  1770.         DragAcceptFiles(hWnd,FALSE);
  1771.    // lgk if we are busy here we must kill any active task
  1772.    if (check_busy())
  1773.      {
  1774.        DoPrintf("Killing active thread ... \n");
  1775.        TerminateThread(threadhandle,1);
  1776.        mirrorinprogress = FALSE;
  1777.        turnonlistwindows();
  1778.        set_busy(FALSE);
  1779.      }
  1780.         PostQuitMessage(0);  // Quit the application
  1781.       } else
  1782.         DestroyWindow(hWnd);
  1783.         DeleteCriticalSection(&busy_variable);
  1784.       break;
  1785.  
  1786.     default:
  1787.       if(!SubProcessAsync(hWnd,Message,wParam,lParam))
  1788.         return DefWindowProc(hWnd, Message, wParam, lParam);
  1789.   }
  1790.   return 0L;
  1791. } // End of WndProc
  1792.  
  1793. /************************************************************************/
  1794. /* Misc Dialog Window Procedures                                        */
  1795. /************************************************************************/
  1796. BOOL CALLBACK WS_AboutMsgProc(HWND hWndDlg, UINT Message, 
  1797.                                 WPARAM wParam, LPARAM lParam)
  1798. {
  1799.  char buf[40];
  1800.   
  1801.  switch(Message)
  1802.  {
  1803.  
  1804.   case WM_INITDIALOG:
  1805.      {
  1806.      {
  1807.        struct hostent FAR *hostptr;
  1808.        struct in_addr *iptr;
  1809.        
  1810.          cwCenter(hWndDlg, 0);
  1811.          if(gethostname((LPSTR)buf,
  1812.              MAXHOSTNAMELEN)!=SOCKET_ERROR) 
  1813.            {
  1814.              if((hostptr=gethostbyname(buf))!=NULL) 
  1815.               {
  1816.                iptr=(struct in_addr *)*(hostptr->h_addr_list);
  1817.                wsprintf(szString,"%s [%s]",buf,inet_ntoa(*iptr));
  1818.               } 
  1819.              else lstrcpy(szString,buf);
  1820.              SetDlgItemText(hWndDlg,DLG_ABT_L2,szString);
  1821.            }
  1822.      }
  1823.      SetDlgItemText(hWndDlg,DLG_ABT_L1,
  1824.          (LPSTR)WSAData.szDescription);
  1825.      wsprintf(buf,"Version %s",VERSION);
  1826.      SetDlgItemText(hWndDlg,DLG_VERSION,buf);
  1827.      break;
  1828.   }
  1829.  
  1830.  
  1831.       case WM_CTLCOLORBTN:
  1832.           if(LOWORD(lParam)<10) return((BOOL)NULL);
  1833.  
  1834.      case WM_CTLCOLORDLG:
  1835.      case WM_CTLCOLORSTATIC:
  1836.           SetBkColor((HDC) wParam, RGB(192,192,192));
  1837.         return (BOOL)hbrGray1;
  1838.         break;
  1839.  
  1840.  
  1841.    case WM_CLOSE:
  1842.      PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L);
  1843.      break;
  1844.  
  1845.    case WM_COMMAND:
  1846.      switch(LOWORD(wParam))
  1847.      {
  1848.        case IDOK:
  1849.          EndDialog(hWndDlg, TRUE);
  1850.          break;
  1851.        case IDCANCEL:
  1852.          EndDialog(hWndDlg, FALSE);
  1853.          break;
  1854.      }
  1855.      break;
  1856.     default:
  1857.         return FALSE;
  1858.   }
  1859.   return TRUE;
  1860. }
  1861.  
  1862. BOOL CALLBACK WS_InputMsgProc(HWND hWndDlg, UINT Message,
  1863.                                 WPARAM wParam, LPARAM lParam)
  1864.   switch(Message)
  1865.   {
  1866.      case WM_GETDLGCODE:
  1867.      return DLGC_WANTALLKEYS;
  1868.      break;
  1869.  
  1870.      case WM_KEYDOWN:
  1871.       DoPrintf("a key is down");
  1872.       break;
  1873.  
  1874.       case WM_CHAR:
  1875.       DoPrintf("wmchar a key is down");
  1876.       break;
  1877.  
  1878.     case WM_INITDIALOG:
  1879.       SetDlgItemText(hWndDlg,DLG_PROMPT,szDlgPrompt);
  1880.       SetDlgItemText(hWndDlg,DLG_EDIT,szDlgEdit);
  1881.       cwCenter(hWndDlg, 0);                                            
  1882.       break;
  1883.  
  1884.  
  1885.         case WM_CTLCOLORBTN:
  1886.              if(LOWORD(lParam)<10) return((LRESULT)NULL);
  1887.  
  1888.         case WM_CTLCOLORDLG:
  1889.         case WM_CTLCOLORSTATIC:
  1890.         SetBkColor((HDC) wParam, RGB(192,192,192));
  1891.          return(LRESULT)hbrGray1;
  1892.           break;
  1893.   
  1894.      case WM_CLOSE:
  1895.       PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L);
  1896.       break;
  1897.  
  1898.     case WM_COMMAND:
  1899.       switch(LOWORD(wParam))
  1900.       {
  1901.         case IDOK:
  1902.           GetDlgItemText(hWndDlg,DLG_EDIT,szDlgEdit,70);
  1903.           EndDialog(hWndDlg, TRUE);
  1904.           break;
  1905.         case IDCANCEL:
  1906.           EndDialog(hWndDlg, FALSE);
  1907.           break;
  1908.       }
  1909.       break;
  1910.     default:
  1911.       return FALSE;
  1912.   }
  1913.   return TRUE;
  1914. }
  1915.  
  1916. BOOL CALLBACK WS_StatMsgProc(HWND hWndDlg, UINT Message,
  1917.                                WPARAM wParam, LPARAM lParam)
  1918.   switch(Message)
  1919.   {
  1920.     case WM_INITDIALOG:
  1921.       SetDlgItemText(hWndDlg,DLG_EDIT,szViewer);
  1922.       SetDlgItemText(hWndDlg,DLG_MAILADDR,szMailAddress);
  1923.       if(fType==TYPE_A)
  1924.         CheckRadioButton(hWndDlg,RB_ASCII,RB_L8,RB_ASCII);
  1925.       else if(fType==TYPE_I)
  1926.         CheckRadioButton(hWndDlg,RB_ASCII,RB_L8,RB_BINARY);
  1927.       else
  1928.         CheckRadioButton(hWndDlg,RB_ASCII,RB_L8,RB_L8);
  1929.       CheckDlgButton(hWndDlg,CKB_VERBOSE,bVerbose);
  1930.       CheckDlgButton(hWndDlg,CKB_BELL,bBell);
  1931.       CheckDlgButton(hWndDlg,CKB_GLOBBING,bDoGlob);
  1932.       CheckDlgButton(hWndDlg,CKB_HASH,bHash);
  1933.       CheckDlgButton(hWndDlg,CKB_PROMPT,bInteractive);
  1934.       CheckDlgButton(hWndDlg,CKB_MCASE,bMCase);
  1935.       CheckDlgButton(hWndDlg,CKB_PORT_CMDS,bSendPort);
  1936.       CheckDlgButton(hWndDlg,CKB_RECV_UNIQUE,bRecvUniq);
  1937.       CheckDlgButton(hWndDlg,CKB_STOR_UNIQUE,bStorUniq);
  1938.       CheckDlgButton(hWndDlg,CKB_CRSTRIP,bCRstrip);
  1939.       CheckDlgButton(hWndDlg,CKB_AUTOSTART,bAutoStart);
  1940.       break;
  1941.  
  1942.     case WM_CLOSE:
  1943.       PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L);
  1944.       break;
  1945.  
  1946.     case WM_SETCURSOR:
  1947.       if(bCmdInProgress)
  1948.         SetCursor(hWaitCursor);
  1949.       else
  1950.         return FALSE;
  1951.       break;
  1952.  
  1953.         case WM_CTLCOLORBTN:
  1954.              if(LOWORD(lParam)<10) return((LRESULT)NULL);
  1955.        case WM_CTLCOLORDLG:
  1956.         case WM_CTLCOLORSTATIC:
  1957.          SetBkColor((HDC) wParam, RGB(192,192,192));
  1958.           return(LRESULT)hbrGray1;
  1959.           break;
  1960.  
  1961.     case WM_COMMAND:
  1962.       switch(LOWORD(wParam))
  1963.       {
  1964.         case IDOK:
  1965.           if(IsDlgButtonChecked(hWndDlg,RB_ASCII)) fType=TYPE_A;
  1966.           else if(IsDlgButtonChecked(hWndDlg,RB_BINARY)) fType=TYPE_I;
  1967.           else fType=TYPE_L;
  1968.  
  1969.           bVerbose=IsDlgButtonChecked(hWndDlg,CKB_VERBOSE);
  1970.           bBell=IsDlgButtonChecked(hWndDlg,CKB_BELL);
  1971.           bDoGlob=IsDlgButtonChecked(hWndDlg,CKB_GLOBBING);
  1972.           bHash=IsDlgButtonChecked(hWndDlg,CKB_HASH);
  1973.           bInteractive=IsDlgButtonChecked(hWndDlg,CKB_PROMPT);
  1974.           bMCase=IsDlgButtonChecked(hWndDlg,CKB_MCASE);
  1975.           bSendPort=IsDlgButtonChecked(hWndDlg,CKB_PORT_CMDS);
  1976.           bRecvUniq=IsDlgButtonChecked(hWndDlg,CKB_RECV_UNIQUE);
  1977.           bStorUniq=IsDlgButtonChecked(hWndDlg,CKB_STOR_UNIQUE);
  1978.           bCRstrip=IsDlgButtonChecked(hWndDlg,CKB_CRSTRIP);
  1979.           bAutoStart=IsDlgButtonChecked(hWndDlg,CKB_AUTOSTART);
  1980.  
  1981.           GetDlgItemText(hWndDlg,DLG_EDIT,szViewer,70);
  1982.           GetDlgItemText(hWndDlg,DLG_MAILADDR,szMailAddress,127);
  1983.           EndDialog(hWndDlg, TRUE);
  1984.           break;
  1985.         case IDCANCEL:
  1986.           EndDialog(hWndDlg, FALSE);
  1987.           break;
  1988.       }
  1989.       break;    // End of WM_COMMAND
  1990.     default:
  1991.       return FALSE;
  1992.   }
  1993.   return TRUE;
  1994. }
  1995.  
  1996. /************************************************************************/
  1997. /* nCwRegisterClasses Function                                          */
  1998. /* The following function registers all the classes of all the windows  */
  1999. /* associated with this application. The function returns an error code */
  2000. /* if unsuccessful, otherwise it returns 0.                             */
  2001. /************************************************************************/
  2002. int nCwRegisterClasses(void)
  2003. {
  2004.   WNDCLASS   wndclass;    // struct to define a window class
  2005.   memset(&wndclass, 0x00, sizeof(WNDCLASS));
  2006.  
  2007.   // load WNDCLASS with window's characteristics
  2008.   wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW;
  2009.   wndclass.lpfnWndProc = WndProc;
  2010.   // Extra storage for Class and Window objects
  2011.   wndclass.cbClsExtra = 0;
  2012.   wndclass.cbWndExtra = 0;
  2013.   wndclass.hInstance = hInst;
  2014.   wndclass.hIcon = LoadIcon(hInst, szAppName);
  2015.   wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  2016.   // Create brush for erasing background
  2017.   wndclass.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(192,192,192));
  2018.   wndclass.lpszMenuName = NULL; // szAppName;   /* Menu Name is App Name */
  2019.   wndclass.lpszClassName = szAppName; /* Class Name is App Name */
  2020.   if(!RegisterClass(&wndclass))
  2021.     return -1;
  2022.   return(0);
  2023. } // End of nCwRegisterClasses
  2024.  
  2025. /************************************************************************/
  2026. /*  cwCenter Function                                                   */
  2027. /*  centers a window based on the client area of its parent             */
  2028. /************************************************************************/
  2029. void cwCenter(hWnd, top)
  2030. HWND hWnd;
  2031. int top;
  2032. {
  2033.   POINT      pt;
  2034.   RECT       swp;
  2035.   RECT       rParent;
  2036.   int        iwidth;
  2037.   int        iheight;
  2038.  
  2039.   // get the rectangles for the parent and the child
  2040.   GetWindowRect(hWnd, &swp);
  2041.  
  2042.   // calculate the height and width for MoveWindow
  2043.   iwidth = swp.right - swp.left;
  2044.   iheight = swp.bottom - swp.top;
  2045.  
  2046.   if(IsIconic(hWndMain))
  2047.     MoveWindow(hWnd, 0, 0, iwidth, iheight, FALSE);
  2048.   else {
  2049.     GetClientRect(hWndMain, &rParent);
  2050.  
  2051.     // find the center point and convert to screen coordinates
  2052.     pt.x = (rParent.right - rParent.left) / 2;
  2053.     pt.y = (rParent.bottom - rParent.top) / 2;
  2054.     ClientToScreen(hWndMain, &pt);
  2055.  
  2056.     // calculate the new x, y starting point
  2057.     pt.x = pt.x - (iwidth / 2);
  2058.     pt.y = pt.y - (iheight / 2);
  2059.  
  2060.     // top will adjust the window position, up or down
  2061.     if(top)
  2062.       pt.y = pt.y + top;
  2063.  
  2064.     // move the window
  2065.     MoveWindow(hWnd,max(0,pt.x),max(0,pt.y), iwidth, iheight, FALSE);
  2066.   }
  2067. } // end of cwCenter
  2068.  
  2069. /************************************************************************/
  2070. /*  CwUnRegisterClasses Function                                        */
  2071. /*  Deletes any refrences to windows resources created for this         */
  2072. /*  application, frees memory, deletes instance, handles and does       */
  2073. /*  clean up prior to exiting the window                                */
  2074. /************************************************************************/
  2075. void CwUnRegisterClasses(void)
  2076. {
  2077.   WNDCLASS   wndclass;    // struct to define a window class
  2078.   memset(&wndclass, 0x00, sizeof(WNDCLASS));
  2079.  
  2080.   GetClassInfo(hInst, szAppName, &wndclass);
  2081.   DeleteObject(wndclass.hbrBackground);
  2082.   UnregisterClass(szAppName, hInst);
  2083.   UnregisterClass(DBUGWNDCLASS,hInst);
  2084. } // End of CwUnRegisterClasses
  2085.  
  2086.