home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / relog1.exe / RELOG.C next >
C/C++ Source or Header  |  1994-01-04  |  28KB  |  1,007 lines

  1. /*****************************************************************
  2.                     DISCLAIMER
  3.  
  4. Novell, Inc. makes no representations or warranties with respect to
  5. any NetWare software, and specifically disclaims any express or
  6. implied warranties of merchantability, title, or fitness for a
  7. particular purpose.
  8.  
  9. Distribution of any NetWare software is forbidden without the
  10. express written consent of Novell, Inc.  Further, Novell reserves
  11. the right to discontinue distribution of any NetWare software.
  12.  
  13. Novell is not responsible for lost profits or revenue, loss of use
  14. of the software, loss of data, costs of re-creating lost data, the
  15. cost of any substitute equipment or program, or claims by any party
  16. other than you.  Novell strongly recommends a backup be made before
  17. any software is installed.   Technical support for this software
  18. may be provided at the discretion of Novell.
  19. *****************************************************************/
  20.  
  21. /********************************************************************
  22. Source: RELOG.C  - Reattaches File Server and remaps the drives
  23. Date  : 01/04/94 - original source
  24. -----------------------------------------------------------------------
  25.  
  26. Purpose:
  27.    demonstrate how to reattach to fileservers and remaps the drives
  28.    associated with those fileservers without exitting a program.
  29. -----------------------------------------------------------------------
  30. 01/04/94 - DReeves & MSpano - initial release.
  31. -----------------------------------------------------------------------
  32. ***********************************************************************/
  33.  
  34. #include <io.h>                    /* Borland header files */
  35. #include <fcntl.h>
  36. #include <share.h>
  37. #include <sys\stat.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42. #include <conio.h>
  43. #include <direct.h>
  44. #include <dos.h>
  45.  
  46. /*-----------------------------------------------------------------------*/
  47.  
  48. #include <nit.h>                   /* NWCI header files */
  49. #include <nxt.h>
  50. #include <niterror.h>
  51. #include <diag.h>
  52.  
  53. /*-----------------------------------------------------------------------*/
  54.  
  55. #define DISPLAYSAVE        1
  56. #define DISPLAYRESET       1
  57.  
  58. #define NOTMAPPED        255
  59. #define LOCAL            128
  60. #define MAXMAPPINGS       32
  61. #define MAXSEARCHDRIVES   16
  62. #define SEARCHDRIVE        1
  63. #define ENDMARKER       0xFF
  64.  
  65. #define CR              0x0D
  66.  
  67. #define IGNORE             0
  68. #define RETRY              1
  69. #define ABORT              2
  70. #define LASTDOSDRIVE          5
  71. /*-----------------------------------------------------------------------*/
  72.  
  73. struct searchDrives
  74. {
  75.    BYTE vector[MAXSEARCHDRIVES]; /* stores search drive order (indexes) */
  76.    struct {
  77.       char path[255];
  78.       BYTE search;      /* Flag - marked if search drive                */
  79.       BYTE dtype;       /* drive type - used, network, local            */
  80.       BYTE rootEnd;     /* index into 'path' at end of the root portion */
  81.       WORD connID;      /* server connection for each mapped drive      */
  82.       } drive[MAXMAPPINGS];
  83. }  maps;
  84.  
  85.  
  86. struct serverList
  87. {
  88.     char fileServerName[48]; /* server name */
  89.     BYTE network[4];         /* server's network number */
  90.     BYTE node[6];            /* physical node address */
  91.     BYTE socket[2];          /* socket number */
  92.     BYTE down;               /* flag is set if fileserver is down */
  93.     BYTE connID;             /* server connection for file server name */
  94. } serverInfo[9];            /* want this to be 1-based */
  95.  
  96. static char *err_msg[]=     /* INT 24 messages */
  97. {     "write protect",
  98.     "unknown unit",
  99.     "drive not ready",
  100.     "unknown command",
  101.     "data error (CRC)",
  102.     "bad request",
  103.     "seek error",
  104.     "unknown media type",
  105.     "sector not found",
  106.     "printer out of paper",
  107.     "write fault",
  108.     "read fault",
  109.     "general failure",
  110.     "reserved",
  111.     "reserved",
  112.     "invalid disk change"
  113. };
  114.  
  115. /**************************
  116.     Global Variables
  117. **************************/
  118. BeginDiagnosticStruct destination;
  119.  
  120. BYTE  dirHandleNum;
  121. char  dirPath[255];
  122. char  thePath[255];
  123. char  tmpPath[255];
  124. char  serverName[48];
  125. char  volume[48];
  126. int   cCode;
  127. int   drv;
  128. WORD  connID,
  129.       defaultConnID;
  130.  
  131. char far *fsNamePtr;
  132. char far *idNamePtr;
  133. char far *driveFlagPtr;
  134. char far *driveConnIDPtr;
  135. char far *driveHndlPtr;
  136.  
  137.  
  138. // function prototypes
  139. void GetServerInfo ( void );
  140. void SaveDriveMappings(void );
  141. int Handler24 ( int,int,int,int );
  142.     int ErrorWin ( char * );
  143.     void CleanShell ( int );
  144.     void DeleteMapDrives ( int );
  145. void ReConnectServer ( int );
  146.     int  MapRoot(int, char far *);
  147.     void ResetDriveMappings ( char *, WORD );
  148.  
  149. void PingServers ( void );
  150. void main ( void );
  151.  
  152. /***************************************************************************
  153. ** Set pointers to the various tables in the Shell
  154. ***************************************************************************/
  155. void GetServerInfo ( void )
  156. {
  157.     BYTE compare;
  158.     int entries = 1;
  159.     union REGS inregs, outregs;
  160.     struct SREGS segregs;
  161.     //
  162.     memset ( serverInfo, 0, sizeof ( serverInfo ) );
  163.  
  164.     // Server Connection Table
  165.     segread(&segregs);
  166.  
  167.     inregs.h.ah = 0xEF;
  168.     inregs.h.al = 0x03;
  169.     intdosx(&inregs,&outregs,&segregs);
  170.     idNamePtr = MK_FP(segregs.es,outregs.x.si);
  171.  
  172.  
  173.     // Server Name Table
  174.     inregs.x.ax = 0xEF04;
  175.     intdosx (&inregs,&outregs,&segregs);
  176.     fsNamePtr = MK_FP(segregs.es,outregs.x.si);
  177.  
  178.  
  179.     //Drive Flag Table
  180.     inregs.x.ax = 0xEF01;
  181.     intdosx (&inregs,&outregs,&segregs);
  182.     driveFlagPtr = MK_FP(segregs.es,outregs.x.si);
  183.  
  184.  
  185.     //Drive Connection Table
  186.     inregs.x.ax = 0xEF02;
  187.     intdosx (&inregs,&outregs,&segregs);
  188.     driveConnIDPtr = MK_FP(segregs.es,outregs.x.si);
  189.  
  190.     //Drive Handle Table
  191.     inregs.x.ax = 0xEF00;
  192.     intdosx (&inregs,&outregs,&segregs);
  193.     driveHndlPtr = MK_FP(segregs.es,outregs.x.si);
  194.  
  195.     /* copy info from Shell into serverInfo[] */
  196.  
  197.     while ( entries < 9 )
  198.     {
  199.         compare = *idNamePtr;
  200.  
  201.         /* copy info only if the Slot In Use is set in the shell's
  202.          * Connection ID Table
  203.          */
  204.  
  205.         if ( compare == 0xFF )
  206.         {
  207.             memmove ( serverInfo[entries].fileServerName,fsNamePtr,48 );
  208.             memmove ( serverInfo[entries].network,idNamePtr+2,4 );
  209.             memmove ( serverInfo[entries].node,idNamePtr+6, 6);
  210.             memmove ( serverInfo[entries].socket,idNamePtr+12,2 );
  211.             serverInfo[entries].connID = entries;
  212.         }
  213.         entries ++;
  214.  
  215.         /* advance pointers */
  216.  
  217.         fsNamePtr = fsNamePtr +48;
  218.         idNamePtr = idNamePtr +32;
  219.     }
  220.  
  221.     /* reset pointers to the beginning of the tables */
  222.  
  223.     fsNamePtr = fsNamePtr -384;
  224.     idNamePtr = idNamePtr -256;
  225.  
  226. }    /* end GetServerInfo () */
  227.  
  228. /****************************************************************************
  229. ** saves all mapped drives, placing respective information into the
  230. ** control structure
  231. ****************************************************************************/
  232. void SaveDriveMappings()
  233. {
  234.     int drv, I;
  235.     char *pntr,*pntr2, *tpntr, tchr;
  236.  
  237.  
  238.     for (drv = 0; drv < MAXMAPPINGS; drv++)
  239.     {
  240.  
  241.         maps.drive[drv].dtype = NOTMAPPED;     /* is not being used       */
  242.         maps.drive[drv].rootEnd = 0;           /* ?? if mapped root yet   */
  243.  
  244.         cCode = GetDriveInformation( (BYTE)drv,
  245.                                      &maps.drive[drv].connID,
  246.                                      &dirHandleNum );
  247.  
  248.         /* determine if local drive, permament or temporary or such
  249.         ** a combination */
  250.  
  251.         if ( cCode == LOCAL )
  252.         {
  253.             maps.drive[drv].dtype = (BYTE)LOCAL;
  254.             maps.drive[drv].connID = 0;         /* no connection ID */
  255.         } /* if */
  256.  
  257.         if ( dirHandleNum )
  258.         {
  259.  
  260.             /* get filer server name if not local drv */
  261.  
  262.             GetFileServerName ( maps.drive[drv].connID,maps.drive[drv].path );
  263.  
  264.             /* must set preferred connection to obtain the path   */
  265.             /* from the required server.                          */
  266.  
  267.             if ( connID != maps.drive[drv].connID )
  268.             {
  269.                 connID = maps.drive[drv].connID;
  270.                 SetPreferredConnectionID ( maps.drive[drv].connID );
  271.             } /* if */
  272.  
  273.             if ( GetDirectoryPath ( dirHandleNum,dirPath ) == 0 )
  274.             {
  275.                 maps.drive[drv].dtype = (BYTE)cCode;
  276.                 strcat ( maps.drive[drv].path,"\\" );
  277.                 strcat ( maps.drive[drv].path,dirPath );
  278.  
  279.                 /* Check if MAPped ROOT */
  280.  
  281.                 sprintf ( thePath,"%c:",drv + 'A' );  /* set drive letter */
  282.  
  283.                 /* obtain the path for the drive. NOTE: if mapped root   */
  284.                 /* the MAP ROOTed portion is not returned.               */
  285.  
  286.                 ParsePath ( thePath, serverName, volume, tmpPath );
  287.  
  288.                 /* if a 'path' was returned then get rid of trailing '\' */
  289.  
  290.                 if ( tmpPath[0] )
  291.                 {
  292.                     tmpPath[strlen(tmpPath) - 1] = NULL;
  293.                 }
  294.  
  295.                 /* To check if this is a MAPped ROOT, compare the paths  */
  296.                 /* returned from the 'ParsePath' api and the path we got */
  297.                 /* back from the 'GetDirectoryPath' api. If the paths do */
  298.                 /* NOT match we found a MAPped ROOT.  We must also       */
  299.                 /* determine the MAP ROOTed portion and any path off of  */
  300.                 /* the root                                              */
  301.  
  302.                 if ( strcmp ( tmpPath,( strchr ( dirPath,':' ) + 1 ) ) )
  303.                 {
  304.  
  305.                     /* calculate index where the root ends ('\') */
  306.  
  307.                     maps.drive[drv].rootEnd =
  308.                                (BYTE)( strstr(maps.drive[drv].path,tmpPath) -
  309.                                maps.drive[drv].path );
  310.  
  311.                     /* force NULL over the '\', the path off of the root  */
  312.                     /* can now be obtained via the path[rootEnd]          */
  313.  
  314.                     maps.drive[drv].path[maps.drive[drv].rootEnd - 1] = NULL;
  315.                 }
  316.             } /* if */
  317.         } /* if */
  318.     } /* for */
  319.  
  320.     /* use the PATH environment variable to obtain the             */
  321.     /* search drive order which also includes local search paths.  */
  322.  
  323.     strcpy ( thePath, strupr( getenv ("PATH") ) );
  324.  
  325.     if ( thePath[0] != NULL )
  326.     {
  327.         drv = 0;
  328.         pntr = thePath;
  329.  
  330.         /* loop all of PATH if processed */
  331.  
  332.         while ( ( drv < MAXSEARCHDRIVES ) && ( pntr = strchr(pntr,':' ) ) )
  333.         {
  334.             tpntr = pntr;
  335.  
  336.             /* if character after ':' = '.' then it's a search mapping, */
  337.             /* otherwise it's a local drive specification               */
  338.  
  339.             if ( *(pntr + 1) == '.' )
  340.             {
  341.                 maps.vector[drv] = *(pntr - 1) - 'A';
  342.                 maps.drive[maps.vector[drv]].search = SEARCHDRIVE;
  343.  
  344.                 drv++;     /* advanced to next drive in path */
  345.             }
  346.             else
  347.             {
  348.                 /* Local search drive. Find next available location in the  */
  349.                 /* drive table and assign the correct vector value          */
  350.  
  351.                 for ( I = 0; ( maps.drive[I].dtype != NOTMAPPED ) &&
  352.                              ( I < MAXMAPPINGS); I++ );
  353.  
  354.                 if ( I < MAXMAPPINGS )
  355.                 {
  356.                     /* check for the ';' following each drive specifier.  */
  357.                     /* NOTE: on last one there may not be one so check    */
  358.                     /* for   NULL instead                                 */
  359.  
  360.                     if ( ( pntr2 = strchr (pntr,';' ) ) == NULL )
  361.                     {
  362.                         pntr2 = strchr ( pntr, '\0' );
  363.                     }
  364.  
  365.                     if ( pntr2 )
  366.                     {
  367.                         tchr = *pntr2;
  368.                         *pntr2 = '\0';
  369.                         pntr--;
  370.  
  371.                         /* update the search drive order */
  372.  
  373.                         maps.vector[drv] = (BYTE)I;
  374.                         maps.drive[I].dtype = 1;
  375.                         maps.drive[I].search = SEARCHDRIVE;
  376.  
  377.                         /* copy the local drive specification */
  378.  
  379.                         strcpy ( maps.drive[I].path,pntr );
  380.  
  381.                         if (tchr != NULL)
  382.                         {
  383.                             *pntr2 = '|';
  384.                         }
  385.  
  386.                         drv++;     /* advanced to next drive in path */
  387.                     }/* end if */
  388.                 } /* end if */
  389.             } /* else */
  390.  
  391.             /* 0xFF marks end of search drive vector */
  392.  
  393.             if (drv <= MAXSEARCHDRIVES) maps.vector[drv] = ENDMARKER;
  394.  
  395.             *tpntr = ' ';    /* must STEP over current ':' for next search */
  396.          } /* while */
  397.     }/* end if */
  398. } /* SaveDriveMappings */
  399.  
  400. /****************************************************************************
  401. ** Function called by Int 24 Handler when other types of errors occur
  402. ****************************************************************************/
  403. int ErrorWin ( char *msg )
  404. {
  405.     int retval;
  406.     //
  407.     cputs ( msg );
  408.  
  409.     while ( 1 )
  410.     {
  411.         retval = getch ();
  412.         if (retval == 'a' || retval == 'A')
  413.         {
  414.             retval = ABORT;
  415.             break;
  416.         }
  417.         if (retval == 'r' || retval == 'R')
  418.         {
  419.             retval = ABORT;
  420.             break;
  421.         }
  422.         if (retval == 'i' || retval == 'I')
  423.         {
  424.             retval = ABORT;
  425.             break;
  426.         }
  427.     }
  428.     return ( retval );
  429. }
  430.  
  431. #pragma warn -par
  432.  
  433. /***************************************************************************
  434. ** Critical Error Handler
  435. ***************************************************************************/
  436. int Handler24 ( int errval, int ax, int bp,int si )
  437. {
  438.     BYTE     componentList[54], majorRevisionNumber, minorRevisionNumber;
  439.     int      drive, entries, fsNameLen, retval, i;
  440.     int      errorno;
  441.     WORD     maxConnections,availableConnections;
  442.     static   char msg[80];
  443.     unsigned di;
  444.     //
  445.  
  446.     /* error number that is returned from DOS */
  447.     di = _DI;
  448.  
  449.     if ( ax < 0 )
  450.     {
  451.         ErrorWin ( "Device error" );
  452.         hardretn ( ABORT );
  453.     }
  454.  
  455.     /* the information concerning which drive letter failed will be */
  456.     /* returned in the BH register                                  */
  457.  
  458.     asm {  /* must place this bracket here for inline assembly to work */
  459.          xor   bl,bl
  460.          xchg  bh,bl
  461.          mov   drive,bx
  462.     }
  463.  
  464.     /* check for General Failure and Network drive */
  465.     /* drv is a global var and set in the main ()  */
  466.     if ( ( ( di && 0xC ) == 0x01 ) && ( drv > LASTDOSDRIVE ) )
  467.     {
  468.         entries = 1;
  469.  
  470.         while ( entries < 9 )
  471.         {
  472.             fsNameLen = strlen ( serverInfo[entries].fileServerName );
  473.  
  474.  
  475.             /* look for fileserver name that has gone down */
  476.  
  477.             retval = strncmp ( serverInfo[entries].fileServerName,
  478.                                maps.drive[drive].path,
  479.                                fsNameLen );
  480.  
  481.             if ( retval == 0 )
  482.                 break;      /* found */
  483.  
  484.             entries++;
  485.         }
  486.         printf ("drive # %d has been down\n",drive);
  487.         printf ( "Server %s has been down, %d\n",
  488.                   serverInfo[entries].fileServerName, cCode );
  489.  
  490.         CleanShell ( serverInfo[entries].connID );
  491.         serverInfo[entries].down = 1;   /* set flag that server is down */
  492. //        IPXCloseSocket ( tempSocket );
  493.         hardretn(ABORT);
  494.     }
  495.  
  496.     else
  497.     {
  498.         errorno = di & 0x00FF;
  499.         sprintf (msg,"Error: %s on drive %c\r\n",err_msg[errorno],'A'+drive);
  500.         ErrorWin ( msg );
  501.         hardretn ( ABORT );
  502.     }
  503.  
  504. } /* end Handler24 */
  505.  
  506. #pragma warn +par
  507.  
  508. /****************************************************************************
  509. ** Reset the Slot In Use flag in the Connection ID Table
  510. ****************************************************************************/
  511. void CleanShell ( int connID )
  512. {
  513.     char far *tempPtr;
  514.     int i, chkStr;
  515.     //
  516.     tempPtr = idNamePtr;
  517.  
  518.     /* increment pointer size of table entry */
  519.     idNamePtr = idNamePtr + ( ( connID - 1 ) * 32 );
  520.  
  521.     /* put 0 in the Slot In Use flag for that entry */
  522.     *idNamePtr = 0;
  523.  
  524.     idNamePtr = tempPtr;
  525.  
  526.     DeleteMapDrives ( connID );
  527.  
  528. }   /* end CleanShell () */
  529.  
  530. /****************************************************************************
  531. ** Delete entries from the Drive Handle Table, the Drive Flag Table, and the
  532. ** Drive Connection ID Table
  533. ****************************************************************************/
  534. void DeleteMapDrives ( int connID )
  535. {
  536.     int drv, sdrv, dummy;
  537. //    char drvl, *pntr, chkStr;
  538.     BYTE temp;
  539.     //
  540.     /* delete all drive references to the downed fileserver */
  541.  
  542.     for ( drv = 0; drv < MAXMAPPINGS; drv++ )
  543.     {
  544.         temp = *driveFlagPtr;            /* Clear Drive Flag table */
  545.         if ( ( temp != 0x00) && ( maps.drive[drv].connID == connID ) )
  546.           *driveFlagPtr = 0x00;
  547.         driveFlagPtr = driveFlagPtr + 1;
  548.  
  549.         temp = *driveConnIDPtr;          /* Clear Connection ID table */
  550.         if ( ( temp != 0x00) && ( maps.drive[drv].connID == connID ) )
  551.           *driveConnIDPtr = 0x00;
  552.         driveConnIDPtr = driveConnIDPtr + 1;
  553.  
  554.         temp = *driveHndlPtr;            /* Clear Connection Handle table */
  555.         if ( ( temp != 0x00) && ( maps.drive[drv].connID == connID ) )
  556.           *driveHndlPtr = 0x00;
  557.         driveHndlPtr = driveHndlPtr + 1;
  558.  
  559.     }
  560.     /* reset pointers */
  561.  
  562.     driveFlagPtr = driveFlagPtr - ( MAXMAPPINGS );
  563.     driveConnIDPtr = driveConnIDPtr - ( MAXMAPPINGS );
  564.     driveHndlPtr = driveHndlPtr - ( MAXMAPPINGS );
  565.  
  566. }    /* end DeleteMapDrives () */
  567.  
  568. /***************************************************************************
  569. ** Check the down flag in serverInfo[] and pings those servers using
  570. ** PingNode ()
  571. ***************************************************************************/
  572. void PingServers ( void )
  573. {
  574.     int   entries;
  575.     BYTE  majorRevisionNumber, minorRevisionNumber, componentList[54];
  576.     WORD  maxConnections,availableConnections, SPXconnectionID;
  577.     WORD  tempSocket;
  578.  
  579.     cCode = SPXInitialize( &majorRevisionNumber,
  580.                            &minorRevisionNumber,
  581.                            &maxConnections,
  582.                            &availableConnections);
  583.  
  584.     if ( cCode != 0xFF )
  585.     {
  586.         printf ( "Unable to ping server\n" );
  587.         printf ( "SPXInitialize failed. ccode = %d\n", cCode );
  588.         exit ( 1 );
  589.     }
  590.  
  591.     tempSocket = 0x00;
  592.  
  593.     cCode = IPXOpenSocket ( (BYTE *)&tempSocket, 0 );
  594.  
  595.     if ( cCode != 0 )
  596.     {
  597.         printf ( "Unable to ping server\n" );
  598.         printf ( "IPXOpenSocket failed. ccode = %d\n", cCode );
  599.         IPXCloseSocket ( tempSocket );
  600.         exit (1);
  601.     }
  602.  
  603.     *(WORD *)destination.socket = (WORD)IntSwap ( 0x0456 );
  604.  
  605.  
  606.     for ( entries = 1; entries < 9; entries++ )
  607.     {
  608.  
  609.         /* search only for those servers who are down */
  610.  
  611.         if ( serverInfo[entries].down == 1 )
  612.         {
  613.             /* get the server address */
  614.  
  615.             memmove (destination.network,serverInfo[entries].network,4);
  616.             memmove (destination.node,serverInfo[entries].node,6);
  617.  
  618.             /* call to ping a particular server */
  619.  
  620.             cCode = PingNode ( &destination );
  621.  
  622.             if ( cCode == 0 )
  623.             {
  624.                 printf ( "Server %s is up\n",
  625.                           serverInfo[entries].fileServerName);
  626.                 ReConnectServer ( entries );
  627.             }
  628.         }
  629.     }
  630.     IPXCloseSocket ( tempSocket );
  631.  
  632. } /* end PingServers () */
  633.  
  634. /***********************************************************************
  635. **Ping the Server
  636. ***********************************************************************/
  637. int PingNode ( BeginDiagnosticStruct *destination )
  638. {
  639.     static struct
  640.     {
  641.         BYTE    exclusionCount;
  642.     } IPXReqstPkt = { (BYTE)NULL };
  643.  
  644.     static struct
  645.     {
  646.         BYTE    majorVer;
  647.         BYTE    minorVer;
  648.         WORD    SPXDiagSocket;
  649.         BYTE    compCnt;
  650.         BYTE    compType[53];
  651.     } IPXReplyPkt;
  652.  
  653.     static ECB         IPXSendECB,IPXReceiveECB;
  654.     static IPXHeader   IPXSendPkt,IPXReceivePkt;
  655.           WORD        tempSocket,startTicks,endTicks;
  656.           int         tTime;
  657.     //
  658.     tempSocket = (WORD)0x4545;
  659.     if( IPXOpenSocket((BYTE *)&tempSocket, 0) )
  660.         return 1;
  661.  
  662.     IPXReceiveECB.socketNumber = tempSocket;
  663.     IPXReceiveECB.fragmentCount = 2;
  664.     IPXReceiveECB.fragmentDescriptor[0].size = sizeof(IPXReceivePkt);
  665.     IPXReceiveECB.fragmentDescriptor[1].size = sizeof(IPXReplyPkt);
  666.  
  667.     IPXGetDataAddress((BYTE *)(&IPXReceivePkt),
  668.                      (WORD *)&IPXReceiveECB.fragmentDescriptor[0].address);
  669.  
  670.     IPXGetDataAddress((BYTE *)&IPXReplyPkt,
  671.                      (WORD *)&IPXReceiveECB.fragmentDescriptor[1].address);
  672.  
  673.     IPXGetLocalTarget((BYTE *)destination,
  674.                      (BYTE *)IPXReceiveECB.immediateAddress, &tTime);
  675.  
  676.     IPXListenForPacket(&IPXReceiveECB);
  677.  
  678.  
  679.     IPXSendPkt.destination = *(IPXAddress *)destination;
  680.  
  681.     *(WORD *)IPXSendPkt.destination.socket = (WORD)0x5604;
  682.     *(WORD *)IPXSendPkt.source.socket = tempSocket;
  683.  
  684.     IPXSendPkt.packetType = 4;
  685.  
  686.     IPXGetInternetworkAddress((BYTE *)&IPXSendPkt.source);
  687.  
  688.     IPXGetLocalTarget((BYTE *)IPXSendPkt.destination.network,
  689.                      IPXSendECB.immediateAddress, &tTime);
  690.  
  691.     IPXSendECB.socketNumber = tempSocket;
  692.     IPXSendECB.fragmentCount = 2;
  693.     IPXSendECB.fragmentDescriptor[0].size = sizeof(IPXSendPkt);
  694.     IPXSendECB.fragmentDescriptor[1].size = sizeof(IPXReqstPkt);
  695.  
  696.     IPXGetDataAddress((BYTE *) (&IPXSendPkt),
  697.                      (WORD *) &IPXSendECB.fragmentDescriptor[0].address);
  698.  
  699.     IPXGetDataAddress((BYTE *) &IPXReqstPkt,
  700.                      (WORD *) &IPXSendECB.fragmentDescriptor[1].address);
  701.  
  702.     IPXSendPacket(&IPXSendECB);
  703.  
  704.     while( IPXSendECB.inUseFlag )
  705.         IPXRelinquishControl();
  706.  
  707.     startTicks = IPXGetIntervalMarker();
  708.  
  709.     while( IPXReceiveECB.inUseFlag )
  710.     {
  711.         IPXRelinquishControl();              /* if node does not respond */
  712.         endTicks = IPXGetIntervalMarker();   /* in 4 seconds....         */
  713.         if( endTicks - startTicks > 72 )
  714.             break;
  715.     }
  716.  
  717.     IPXCloseSocket( tempSocket );          /* ....then cancel send */
  718.  
  719.     if( IPXSendECB.completionCode != 0 )
  720.         return IPXSendECB.completionCode;
  721.  
  722.     if( IPXReceiveECB.inUseFlag || IPXReceiveECB.completionCode )
  723.         return IPXReceiveECB.completionCode;   /* no response */
  724.  
  725.     return 0;
  726. }   // end PingNode
  727.  
  728.  
  729. /**************************************************************************
  730. ** Reattach to the fileserver
  731. **************************************************************************/
  732. void ReConnectServer ( int entries )
  733. {
  734.     BYTE netAddress[12];
  735.     char objName[48],            // string containing bindery name
  736.          dirPath[255],            // string containing path specification
  737.          passWord[48],            // string containing object's password
  738.          ch;                    // char holder for getch()
  739.     int  i,                        // index for passWord[]
  740.          cCode;                    // status code from NW functions
  741.     WORD defaultConnectionID,    // connection ID of default file server
  742.          preferredConnectionID;    // connectionID of primary file server
  743.     //
  744.  
  745.     memmove ( netAddress, &serverInfo[entries].network, 12 );
  746.  
  747.     cCode = AttachToFileServerWithAddress
  748.             ( serverInfo[entries].fileServerName,
  749.               &preferredConnectionID, netAddress );
  750.  
  751.     if ( ( cCode ) && ( cCode != 248 ) )
  752.         printf ( "AttachToFileServer Failed. cCode = %d\n", cCode );
  753.     else
  754.     {
  755.         printf ( "FSName in Reconnect %s\n", serverInfo[entries].fileServerName );
  756.  
  757.  
  758.         /* get the new connection ID since it could have changed */
  759.         SetPreferredConnectionID ( preferredConnectionID );
  760.  
  761.         printf ( "Enter User Name and Password to Login to File Server\n" );
  762.         printf ( "----------------------------------------------------\n" );
  763.         printf ( "User Name : " );
  764.         strupr ( gets ( objName ) );
  765.         printf ( "\nPassword  : " );
  766.         i = 0;
  767.         do
  768.         {
  769.             ch = getch ();
  770.             passWord[i++] = toupper ( ch );
  771.             if ( ch == CR )
  772.             {
  773.                 passWord[i - 1] = '\0';
  774.             }
  775.         } while ( ch != CR );
  776.         printf ( "\n\n" );
  777.         //
  778.         cCode = LoginToFileServer ( objName, OT_USER, passWord );
  779.         if ( cCode )
  780.         {
  781.             printf ( "LoginToFileServer returned a [%X]\n", cCode );
  782.             DetachFromFileServer ( preferredConnectionID );
  783.             exit ( -1 );
  784.         }
  785.         else
  786.         {
  787.             serverInfo[entries].connID = preferredConnectionID;
  788.             serverInfo[entries].down = 0;
  789.             ResetDriveMappings ( &serverInfo[entries].fileServerName,
  790.                                  preferredConnectionID );
  791.         }
  792.     }    // end if-else
  793. }    // end ReconnectServer () */
  794.  
  795. /********************************************************************
  796. ** Maps the supplied drive and path as a Mapped Root
  797. ** Input Parameters:
  798. **    int drv - A = 0, B = 1...
  799. **    char far *rpath - must be FAR pointer to string
  800. ********************************************************************/
  801. int MapRoot ( int drv, char far *rpath )
  802. {
  803.     union   REGS    regs;
  804.     struct  SREGS   sregs;
  805.  
  806.     regs.x.ax = 0xE905;             /* Map Root function code - AX = E905h  */
  807.     regs.x.bx = drv + 1;            /* A = 1, B = 2....                     */
  808.     regs.x.dx = FP_OFF(rpath);      /* DX - offset of path                  */
  809.     sregs.ds  = FP_SEG(rpath);      /* DS - segment of path                 */
  810.  
  811.     intdosx(®s,®s,&sregs);
  812.     return(regs.h.al);               /* error code return in AL */
  813. }  /* end MapRoot() */
  814.  
  815. /*******************************************************************
  816. ** Restore the the drive mappings saved in the conrol structure
  817. ********************************************************************/
  818. void ResetDriveMappings ( char *serverName, WORD newConnID )
  819. {
  820.     int drv, len;
  821.     char drvl, *pntr;
  822.     unsigned sdrv, dummy;
  823.     //
  824.  
  825.     /* 1st reset a the non-search drives.  Actually all mapped drives */
  826.     /* are reset, since search drives are only mapped drives that are */
  827.     /* specified in the PATH environment variable.                    */
  828.  
  829.  
  830.     for ( drv = LASTDOSDRIVE; drv < MAXMAPPINGS; drv++ )
  831.     {
  832.         /* if connection ID specified for drive, then reset it,  */
  833.         /* otherwise it's a local mapping only                   */
  834.  
  835.         len = strlen ( serverName );
  836.  
  837.         if ( strncmp ( serverName,maps.drive[drv].path,len ) == 0 )
  838.         {
  839.             /* if MAPped ROOT, then set the root and then modify the */
  840.             /* path off of that root if necessary                    */
  841.  
  842.             if ( maps.drive[drv].rootEnd )
  843.             {
  844.  
  845.                 /* display only non-search drives at this time */
  846.  
  847.                 if ( maps.drive[drv].search != SEARCHDRIVE )
  848.                 {
  849.                     printf ( "\nDrive:  %c := %s \\%s\\",'A' + (char)drv,
  850.                              maps.drive[drv].path,
  851.                              &maps.drive[drv].path[maps.drive[drv].rootEnd]
  852.                            );
  853.                 }
  854.  
  855.                 SetPreferredConnectionID ( newConnID );
  856.  
  857.                 cCode = MapRoot ( drv, (char far *)maps.drive[drv].path );
  858.                 if (cCode)
  859.                 {
  860.                     printf ("\nError MapRoot: %d",cCode );
  861.                     exit (1);
  862.                 }
  863.  
  864.                 /* update the structure with new connection ID */
  865.                 maps.drive[drv].connID = newConnID;
  866.  
  867.                 /* if not at root, then set the path off of the root */
  868.  
  869.                 if ( maps.drive[drv].path[maps.drive[drv].rootEnd] != NULL )
  870.                 {
  871.                     _dos_getdrive ( &sdrv );
  872.                     _dos_setdrive ( drv, &dummy );
  873.                     chdir( &maps.drive[drv].path[maps.drive[drv].rootEnd] );
  874.                     _dos_setdrive ( sdrv, &sdrv );
  875.                 } /* if */
  876.             } /* if */
  877.             else
  878.             {
  879.                 /* display only non-search drives at this time */
  880.  
  881.                 if ( maps.drive[drv].search != SEARCHDRIVE )
  882.                 {
  883.                     printf( "\nDrive:  %c := %s ",'A' + (char)drv,
  884.                             maps.drive[drv].path );
  885.                 }
  886.  
  887.                 drvl = (char)( drv + 'A' );
  888.                 cCode = MapDrive( newConnID, NO_BASE_DRIVE,
  889.                                   maps.drive[drv].path,
  890.                                   DRIVE_ADD, 0, &drvl);
  891.  
  892.                 if ( cCode )
  893.                 {
  894.                     printf ( "\nError MapDrive: %d", cCode );
  895.                     exit(1);
  896.                 } /* if */
  897.  
  898.                 /* update the structure with new connection ID */
  899.                 maps.drive[drv].connID = newConnID;
  900.  
  901.             } /* else */
  902.  
  903.         } /* end if */
  904.  
  905.     } /* for */
  906.  
  907.     /* now display the search drives & create the PATH variable */
  908.  
  909.     printf("\n-----");
  910.  
  911.     pntr = thePath;
  912.  
  913.     for ( drv = 0; ( maps.vector[drv] != ENDMARKER) &&
  914.                    ( drv < MAXSEARCHDRIVES ); drv++ )
  915.     {
  916.         if ( maps.vector[drv] < MAXMAPPINGS )
  917.         {
  918.             /* only reset the a NetWare mapped drives */
  919.             /* NOTE: local search drives set only via */
  920.             /* the PATH variable                      */
  921.  
  922.             if (maps.drive[maps.vector[drv]].connID )
  923.  
  924.             {
  925.                 drvl = maps.vector[drv] + 'A';
  926.  
  927.                 printf ( "\nSearch %2d := [%c:%s",drv + 1, drvl,
  928.                          maps.drive[maps.vector[drv]].path );
  929.  
  930.                 if ( maps.drive[maps.vector[drv]].rootEnd )
  931.                 {
  932.                     printf (" \\%s\\ ",
  933.                             &maps.drive[drv].path[maps.drive[drv].rootEnd] );
  934.                 }
  935.                 printf("]\n");
  936.  
  937.                 /* place the drive letter into the path followed by ':.;' */
  938.                 sprintf ( pntr,"%c:.;",
  939.                           (char)(maps.vector[drv] + 'A' ) );
  940.                 pntr += 4;
  941.             }
  942.             else if ( drv <= LASTDOSDRIVE )
  943.             {
  944.                /* force local drive & path mapping into PATH */
  945.  
  946.                 strcpy ( pntr,maps.drive[maps.vector[drv]].path );
  947.                 if ( pntr = strchr ( pntr,NULL ) )
  948.                 {
  949.                     *pntr++ = ';';
  950.                     *pntr = NULL;
  951.                 }
  952.             } /* else */
  953.         } /* if */
  954.     } /* for */
  955.  
  956.     /*-- UPDATE THE DOS PATH VARIABLE --*/
  957.  
  958.     PutEnvironmentVariable( "PATH", thePath );
  959.  
  960. } /* end ResetDriveMappings () */
  961.  
  962.  
  963. void main ( void )
  964. {
  965.     char ret,strdrv[2];
  966.     int fh,i,entries;
  967.     WORD connectionID;
  968.     BYTE dirHandle;
  969.  
  970.  
  971.     GetServerInfo ();
  972.     defaultConnID = GetDefaultConnectionID();
  973.     SaveDriveMappings();
  974.     harderr ( Handler24 );
  975.  
  976.     printf ( "Go down server\n" );
  977.     printf ( "Press Any Key After Servers Are Down\n" );
  978.     getch();
  979.     printf ( "Searching...\n\n" );
  980.  
  981.     ret = 0x00;
  982.  
  983.     while (ret != 's')
  984.     {
  985.         for (drv = LASTDOSDRIVE; drv < MAXMAPPINGS; drv ++)
  986.         {
  987.             entries = 1;
  988.  
  989.             while ( ( maps.drive[drv].connID ==  serverInfo[entries].connID )
  990.                      && serverInfo[entries].down != 0 )
  991.                 entries++;
  992.  
  993.             strdrv[0] = (char)( drv + 'A' );
  994.             strdrv[1] = ':';
  995.             chdir ( strdrv );
  996.  
  997.         }
  998.         PingServers ();    /* check to see if any servers have returned */
  999.         printf ( "Hit any key to continue; s to quit\n" );
  1000.         ret = getch ();
  1001.         printf ( "\nSearching...\n" );
  1002.     }
  1003.  
  1004.     SetPreferredConnectionID(defaultConnID);
  1005.  
  1006. }  /* main */
  1007.