summaryrefslogtreecommitdiffstats
path: root/private/nw/nwscript/nwapi3.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/nw/nwscript/nwapi3.c1457
1 files changed, 1457 insertions, 0 deletions
diff --git a/private/nw/nwscript/nwapi3.c b/private/nw/nwscript/nwapi3.c
new file mode 100644
index 000000000..5408d286e
--- /dev/null
+++ b/private/nw/nwscript/nwapi3.c
@@ -0,0 +1,1457 @@
+/*************************************************************************
+*
+* NWAPI3.C
+*
+* NetWare routines ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NWAPI3.C $
+*
+* Rev 1.4 18 Apr 1996 16:52:14 terryt
+* Various enhancements
+*
+* Rev 1.3 10 Apr 1996 14:23:20 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.5 13 Mar 1996 18:49:28 terryt
+* Support directory maps
+*
+* Rev 1.4 12 Mar 1996 19:55:10 terryt
+* Relative NDS names and merge
+*
+* Rev 1.2 22 Dec 1995 14:26:02 terryt
+* Add Microsoft headers
+*
+* Rev 1.1 22 Nov 1995 15:41:56 terryt
+* Fix MAP ROOT of search drives
+*
+* Rev 1.0 15 Nov 1995 18:07:38 terryt
+* Initial revision.
+*
+* Rev 1.3 25 Aug 1995 16:23:22 terryt
+* Capture support
+*
+* Rev 1.2 26 Jul 1995 16:02:08 terryt
+* Allow deletion of current drive
+*
+* Rev 1.1 23 Jun 1995 09:49:22 terryt
+* Add error message for mapping over MS network drive
+*
+* Rev 1.0 15 May 1995 19:10:54 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+/*
+Module Name:
+ nwapi3.c
+
+Abstract:
+ can :
+ - view current mapping
+ - create/change a drive mapping
+ - create/change a search drive mapping
+ - map a drive to a fake root
+ - map the next available drive
+
+ SYNTAX (Command line)
+ View current mapping.
+ MAP [drive:]
+ Create or change network drive mappings
+ MAP path
+ MAP drive:=[drive:|path]
+ MAP [DEL[ete] | REM[ove]] drive:
+ Create or change search dirve mappings
+ MAP [INS[ert]] drive:=[drive:|path]
+ Map a drive to a fake root directory
+ MAP ROOT drive:=[drive:|path]
+ Map the next available dirve
+ MAP N[ext] [drive:|path]
+
+
+
+Author : Thierry TABARD (thierryt)
+
+Revision history :
+ - 03/10/94 thierryt started
+ - 05/13/94 congpay rewrote.
+*/
+
+#include <ctype.h>
+#include <direct.h>
+#include "common.h"
+
+/* Local functions*/
+int IsDrive( char * input);
+int GetSearchNumber( char * input);
+int IsNetwareDrive (int driveNum);
+int IsLocalDrive (int driveNum);
+int IsNonNetwareNetworkDrive (int driveNum);
+int GetDriveFromSearchNumber (int searchNumber);
+
+void DisplayDriveMapping(WORD drive);
+void DisplaySearchDriveMapping(int searchNumber);
+
+int ParseMapPath(char * mapPath, char * volName, char * dirPath, char * serverName, int fMapErrorsOn, char *lpCommand);
+int MapDrive (int driveNum, int searchNum, char * mapPath, int bRoot, int bInsert, int fMapErrorsOn, char *lpCommand);
+int MapNonSearchDrive (int driveNum, char *mapPath, int bRoot, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand);
+int MapSearchDrive (int searchNum, int driveNum, char *mapPath, int bInsert, int bRoot, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand);
+int MapNextAvailableDrive (char *mapPath, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand);
+
+void RemoveDriveFromPath(int searchNumber, int fMapErrorsOn);
+int RemoveDrive (WORD drive, int fMapDisplayOn, int fMapErrorsOn);
+void RemoveSearchDrive (int searchNumber, int fMapDisplayOn, int fMapErrorsOn);
+int InsertSearchDrive(int searchNum, int driveNum, int bInsert, char * insertPath);
+
+#define CM_MAP 0
+#define CM_DEL 1
+#define CM_NEXT 2
+#define CM_HELP 3
+#define MAX_INPUT_PATH_LEN 128
+
+int fMapDisplayOn = TRUE;
+int fMapErrorsOn = TRUE;
+int SafeDisk = 2;
+
+int GetFlag (char *buffer, int *pfInsert, int *pfRoot, char **ppPath)
+{
+ int nFlag, nLen;
+ char *lpSpace, *lpTemp;
+
+ if (((*buffer == '/') || (*buffer == '-') || (*buffer == '\\')) &&
+ (*(buffer+1) == '?'))
+ return CM_HELP;
+
+ lpSpace = strchr (buffer, ' ');
+
+ nFlag = CM_MAP; // A bug!
+
+ if (lpSpace == NULL)
+ {
+ *ppPath = buffer;
+ return CM_MAP;
+ }
+
+ nLen = lpSpace - buffer;
+ lpSpace++;
+
+ if (!strncmp(buffer, __DEL__, max (3, nLen)) ||
+ !strncmp(buffer, __REM__, max (3, nLen)))
+ nFlag = CM_DEL;
+ else if (!strncmp(buffer, __NEXT__, nLen))
+ nFlag = CM_NEXT;
+ else if (!strncmp(buffer, __INS__, max (3, nLen)))
+ {
+ *pfInsert = TRUE;
+ if (lpTemp = strchr (lpSpace, ' '))
+ {
+ nLen = lpTemp - lpSpace;
+ if (!strncmp(lpSpace, __ROOT__, nLen))
+ {
+ *pfRoot = TRUE;
+ lpSpace = lpTemp+1;
+ }
+ }
+ }
+ else if (!strncmp(buffer, __ROOT__, nLen))
+ {
+ *pfRoot = TRUE;
+ if (lpTemp = strchr (lpSpace, ' '))
+ {
+ nLen = lpTemp - lpSpace;
+ if (!strncmp(lpSpace, __INS__, max (3, nLen)))
+ {
+ *pfInsert = TRUE;
+ lpSpace = lpTemp+1;
+ }
+ }
+ }
+ else
+ lpSpace = buffer;
+
+ *ppPath = lpSpace;
+
+ return(nFlag);
+}
+
+int Map (char * buffer)
+{
+ WORD status, driveNum;
+ char *lpCommand, *inputPath, *lpEqual;
+ int fRoot, fInsert, fSpace, fCommandHandled;
+ int nFlag, searchNumber, iRet;
+
+ // Fix for NWCS.
+ // NWGetDriveStatus() always returns 1800 on first call for non-Network
+ // drives on NWCS. So we call with c: first to pass the first call.
+ GetDriveStatus (3,
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ lpCommand = strtok (buffer, ";");
+
+ if (lpCommand == NULL)
+ {
+ DisplayMapping();
+ return(0);
+ }
+
+ do
+ {
+ fRoot = FALSE;
+ fInsert = FALSE;
+ fSpace = FALSE;
+ fCommandHandled = TRUE;
+
+ // Make sure first and last char of the command are not spaces.
+ if (*lpCommand == ' ')
+ lpCommand++;
+
+ if (*(lpCommand+strlen (lpCommand)-1) == ' ')
+ *(lpCommand+strlen (lpCommand)-1) = 0;
+
+ if (!strcmp (lpCommand, "DISPLAY ON"))
+ {
+ fMapDisplayOn = TRUE;
+ continue;
+ }
+ else if (!strcmp (lpCommand, "DISPLAY OFF"))
+ {
+ fMapDisplayOn = FALSE;
+ continue;
+ }
+ else if (!strcmp (lpCommand, "ERROR ON") || !strcmp (lpCommand, "ERRORS ON"))
+ {
+ fMapErrorsOn = TRUE;
+ continue;
+ }
+ else if (!strcmp (lpCommand, "ERROR OFF") || !strcmp (lpCommand, "ERRORS OFF"))
+ {
+ fMapErrorsOn = FALSE;
+ continue;
+ }
+
+ nFlag = GetFlag (lpCommand, &fInsert, &fRoot, &inputPath);
+
+ /*
+ * The 4X login program is much more forgiving about spaces
+ * in the map command.
+ */
+ {
+ char *lpTemp;
+ char *lpCur;
+ int inquote = FALSE;
+
+ lpTemp = inputPath;
+ lpCur = inputPath;
+
+ /*
+ * Compress blanks unless the string is quoted
+ */
+ while ( *lpTemp )
+ {
+ if ( *lpTemp == '\"' )
+ {
+ if ( inquote )
+ inquote = FALSE;
+ else
+ inquote = TRUE;
+ }
+ else if ( !inquote &&
+ (( *lpTemp == ' ' ) ||
+ ( *lpTemp == '\t' ) ) )
+ {
+ }
+ else
+ {
+ *lpCur++ = *lpTemp;
+ }
+ lpTemp = NWAnsiNext(lpTemp);
+ }
+ *lpCur = '\0';
+ }
+
+
+ if (nFlag == CM_HELP && fMapErrorsOn)
+ DisplayMessage(IDR_MAP_USAGE);
+ else if (nFlag == CM_NEXT)
+ {
+ if (strchr (inputPath, '=') ||
+ strchr (inputPath, ' ') ||
+ strchr (inputPath, '\t'))
+ fCommandHandled = FALSE;
+ else
+ iRet = MapNextAvailableDrive (inputPath, fMapDisplayOn, fMapErrorsOn, lpCommand);
+ }
+ else if (nFlag == CM_DEL)
+ {
+ if (driveNum = IsDrive (inputPath))
+ iRet = RemoveDrive (driveNum, fMapDisplayOn, fMapErrorsOn);
+ else if (searchNumber = GetSearchNumber(inputPath))
+ RemoveSearchDrive (searchNumber, fMapDisplayOn, fMapErrorsOn);
+ else
+ fCommandHandled = FALSE;
+ }
+ else //nFlag = CM_MAP
+ {
+ if (driveNum = IsDrive (inputPath))
+ {
+ if (fInsert)
+ fCommandHandled = FALSE;
+ else if (fRoot)
+ iRet = MapNonSearchDrive (0, inputPath, TRUE, fMapDisplayOn, fMapErrorsOn, lpCommand);
+ else
+ DisplayDriveMapping(driveNum);
+ }
+ else if (searchNumber = GetSearchNumber (inputPath))
+ {
+ if (fInsert || fRoot)
+ fCommandHandled = FALSE;
+ else
+ DisplaySearchDriveMapping(searchNumber);
+ }
+ else if ((lpEqual = strchr (inputPath, '=')) == NULL)
+ {
+ if (fInsert || strchr (inputPath, ' '))
+ fCommandHandled = FALSE;
+ else
+ {
+ /*
+ * We must cope with MAP K:DIR which means change the
+ * directory on K:
+ */
+ driveNum = 0;
+ if (isalpha(inputPath[0]) && (inputPath[1] == ':'))
+ {
+ driveNum = toupper(inputPath[0]) - 'A' + 1;
+ if ( !IsNetwareDrive(driveNum) )
+ {
+ driveNum = 0;
+ }
+ }
+ iRet = MapNonSearchDrive (driveNum, inputPath, fRoot, fMapDisplayOn, fMapErrorsOn, lpCommand);
+ }
+ }
+ else
+ {
+ if ( ( !fNDS && strchr (lpEqual+2, ' ') )
+ || lpEqual == inputPath) {
+ fCommandHandled = FALSE;
+ }
+ else
+ {
+ if (*AnsiPrev(inputPath, lpEqual) == ' ')
+ {
+ fSpace = TRUE;
+ *(lpEqual-1) = 0;
+ }
+ else
+ *lpEqual = 0;
+
+ if (*(lpEqual+1) == ' ')
+ lpEqual++;
+
+ driveNum = IsDrive (inputPath);
+ searchNumber = GetSearchNumber (inputPath);
+ *(inputPath+strlen(inputPath)) = fSpace? ' ' : '=';
+
+ /*
+ * This is to handle the cases:
+ *
+ * map x:=s3:=sys:public
+ * map s3:=x:=sys:public
+ *
+ * Unfortuneatly the underlying parsing routines
+ * want everything null terminated, so we need
+ * to do the following shuffle.
+ *
+ */
+ if ( driveNum || searchNumber )
+ {
+ if ((strchr (lpEqual+1, '=')) != NULL)
+ {
+ char * lpEqual2;
+ char *tmpPath = _strdup( lpEqual+1 );
+
+ lpEqual2 = strchr (tmpPath, '=');
+
+ if (*AnsiPrev(tmpPath, lpEqual2) == ' ')
+ {
+ fSpace = TRUE;
+ *(lpEqual2-1) = 0;
+ }
+ else
+ *lpEqual2 = 0;
+
+ if (*(lpEqual2+1) == ' ')
+ lpEqual2++;
+
+ if ( searchNumber )
+ {
+ driveNum = IsDrive (tmpPath);
+ }
+ else
+ {
+ searchNumber = GetSearchNumber (tmpPath);
+ }
+
+ if ( driveNum && searchNumber )
+ {
+ lpEqual += (lpEqual2 - tmpPath) + 1;
+ }
+
+ free (tmpPath);
+
+ }
+ }
+
+ if (searchNumber)
+ {
+ iRet = MapSearchDrive (searchNumber, driveNum, lpEqual+1, fInsert, fRoot, fMapDisplayOn, fMapErrorsOn, lpCommand);
+ }
+ else if (driveNum)
+ {
+ if (fInsert)
+ fCommandHandled = FALSE;
+ else
+ iRet = MapNonSearchDrive (driveNum, lpEqual+1, fRoot, fMapDisplayOn, fMapErrorsOn, lpCommand);
+ }
+ else
+ fCommandHandled = FALSE;
+ }
+ }
+ }
+
+ if (!fCommandHandled && fMapErrorsOn)
+ {
+ DisplayMessage(IDR_MAP_INVALID_PATH, lpCommand);
+ }
+ }while ((lpCommand = strtok (NULL, ";")) != NULL);
+
+ return(iRet & 0xFF);
+}
+
+/* Return drive number if input is a drive specified as a letter followed
+ by ':' for example if input is "A:", return 1
+ or netware drive could be specified as *1: for example.
+ Otherwise, return 0.
+ */
+int IsDrive( char * input)
+{
+ unsigned short driveNum = 0, n;
+
+ if (isalpha(input[0]) && (input[1] == ':') && (input[2] == 0))
+ driveNum = toupper(input[0]) - 'A' + 1;
+ else if (input[0] == '*' && isdigit (input[1]) && input[1] != '0')
+ {
+ if (isdigit (input[2]) && input[3] == ':' && input[4] == 0)
+ n = (input[1]-'0')*10+(input[2]-'0');
+ else if (input[2] == ':' && input[3] == 0)
+ n = input[1]-'0';
+
+ if (n)
+ {
+ GetFirstDrive (&driveNum);
+ driveNum += (n-1);
+ if (driveNum < 1 || driveNum > 26)
+ driveNum = 0;
+ }
+ }
+
+ return driveNum;
+}
+
+/*
+ If the input is "Sn:", return n, where n > 0 && n <= 16.
+ Otherwise return 0.
+ */
+int GetSearchNumber( char * input)
+{
+ int searchNumber = 0;
+ char *lpTemp;
+
+ if (input[0] != 'S')
+ return(0);
+
+ lpTemp = input+1;
+ while (*lpTemp && isalpha(*lpTemp))
+ lpTemp++;
+
+ if (strncmp (input, "SEARCH", lpTemp-input))
+ return(0);
+
+ if ((lpTemp[0] > '0') &&
+ (lpTemp[0] <= '9'))
+ {
+ if ((lpTemp[1] == ':') &&
+ (lpTemp[2] == 0))
+ {
+ searchNumber = lpTemp[0] - '0';
+ }
+ else if ((lpTemp[0] == '1') &&
+ (lpTemp[1] >= '0') &&
+ (lpTemp[1] <= '6') &&
+ (lpTemp[2] == ':') &&
+ (lpTemp[3] == 0))
+ {
+ searchNumber = 10 + lpTemp[1] - '0';
+ }
+ }
+
+ return(searchNumber);
+}
+
+/*
+ Return TRUE if the drive is a NetWare drive.
+ FALSE otherwise.
+ */
+int IsNetwareDrive (int driveNum)
+{
+ unsigned int iRet=0;
+ WORD status;
+
+ if (iRet = GetDriveStatus ((unsigned short)driveNum,
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ NULL,
+ NULL,
+ NULL))
+ {
+ return FALSE;
+ }
+
+ return (status & NETWARE_NETWARE_DRIVE);
+}
+
+/*
+ Return TRUE if the drive is a local drive.
+ FALSE otherwise.
+ */
+int IsLocalDrive (int driveNum)
+{
+ unsigned int iRet=0;
+ WORD status;
+
+ if (iRet = GetDriveStatus ((unsigned short)driveNum,
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ NULL,
+ NULL,
+ NULL))
+ {
+ return FALSE;
+ }
+
+ return ((status & NETWARE_LOCAL_DRIVE) && !(status & NETWARE_NETWORK_DRIVE));
+}
+
+/*
+ Return TRUE if the drive is a network drive that is not netware
+ FALSE otherwise.
+ */
+int IsNonNetwareNetworkDrive (int driveNum)
+{
+ unsigned int iRet=0;
+ WORD status;
+
+ if (iRet = GetDriveStatus ((unsigned short)driveNum,
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ NULL,
+ NULL,
+ NULL))
+ {
+ return FALSE;
+ }
+
+ return ((status & NETWARE_NETWORK_DRIVE) && !(status & NETWARE_NETWARE_DRIVE));
+}
+
+/*
+ Return the drive number of search drive n.
+ Return 0 if search drive n does not exist.
+ */
+int GetDriveFromSearchNumber (int searchNumber)
+{
+ char *path;
+ int i;
+
+ path = getenv("PATH");
+
+ for (i = 1; i < searchNumber; i++)
+ {
+ path =strchr (path, ';');
+
+ if (path == NULL || *(path+1) == 0)
+ return(0);
+
+ path++;
+ }
+
+ return(toupper(*path) - 'A' + 1);
+}
+
+/*
+ Display a specific drive's mapping.
+ */
+void DisplayDriveMapping(WORD drive)
+{
+ unsigned int iRet = 0;
+ WORD status = 0;
+ char rootPath[MAX_PATH_LEN], relativePath[MAX_PATH_LEN];
+
+ iRet = GetDriveStatus (drive,
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ rootPath,
+ relativePath,
+ NULL);
+ if (iRet)
+ {
+ DisplayError (iRet, "GetDriveStatus");
+ return;
+ }
+
+ if (status & NETWARE_NETWARE_DRIVE)
+ DisplayMessage(IDR_NETWARE_DRIVE, 'A'+drive-1, rootPath, relativePath);
+ else if ((status & NETWARE_NETWORK_DRIVE) || (status & NETWARE_LOCAL_DRIVE))
+ DisplayMessage(IDR_LOCAL_DRIVE, 'A'+drive-1);
+ else
+ DisplayMessage(IDR_UNDEFINED, 'A'+drive-1);
+}
+
+/*
+ Display a specific search drive's mapping.
+ */
+void DisplaySearchDriveMapping(int searchNumber)
+{
+ unsigned int iRet = 0;
+ char *p, *searchPath;
+ int i;
+ WORD status;
+ char path[MAX_PATH_LEN], rootPath[MAX_PATH_LEN], relativePath[MAX_PATH_LEN];
+
+ searchPath = NWGetPath();
+
+ for (i = 0; i < searchNumber-1; i++)
+ {
+ searchPath = strchr (searchPath, ';');
+ if (searchPath != NULL)
+ searchPath++;
+ else
+ return;
+ }
+
+ p = strchr (searchPath, ';');
+ if (p != NULL)
+ {
+ i= p-searchPath;
+ strncpy (path, searchPath, i);
+ path[i] = 0;
+ }
+ else
+ strcpy (path, searchPath);
+
+ if (isalpha(*path) && *(path+1) == ':')
+ {
+ iRet = GetDriveStatus ((unsigned short)(toupper(*path)-'A'+1),
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ rootPath,
+ relativePath,
+ NULL);
+
+ if (iRet)
+ {
+ DisplayError (iRet, "GetDriveStatus");
+ return;
+ }
+ else
+ {
+ if (status & NETWARE_NETWARE_DRIVE)
+ DisplayMessage(IDR_NETWARE_SEARCH, searchNumber, path, rootPath, relativePath);
+ else
+ DisplayMessage(IDR_LOCAL_SEARCH, searchNumber, path);
+ }
+ }
+ else
+ DisplayMessage(IDR_LOCAL_SEARCH, searchNumber, path);
+}
+
+/*
+ Return TRUE if the mapPath is parsed, FALSE otherwise.
+ */
+int ParseMapPath(char * mapPath, char * volName, char * dirPath, char * serverName, int fMapErrorsOn, char * lpCommand)
+{
+ unsigned int iRet=0;
+ char *pColon, inputPath[MAX_PATH_LEN];
+ int drive, nDriveNum;
+
+ // fix g:=:sys:\public case.
+ if (*mapPath == ':')
+ mapPath++;
+
+ if (strlen (mapPath) > MAX_INPUT_PATH_LEN)
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_INVALID_PATH, mapPath);
+ return FALSE;
+ }
+
+ // Get the drive or volume part if there is one.
+ if (pColon = strchr (mapPath, ':'))
+ {
+ char *directory = pColon+1;
+ int searchNumber;
+
+ // Assing drive: part to input.
+ strncpy (inputPath, mapPath, directory-mapPath);
+ inputPath[directory-mapPath] = 0;
+
+ if (nDriveNum = IsDrive (inputPath))
+ {
+ if (*inputPath == '*')
+ {
+ *inputPath = 'A' + nDriveNum - 1;
+ *(inputPath+1) = ':';
+ *(inputPath+2) = 0;
+ }
+ else if (!IsNetwareDrive(nDriveNum))
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_NOT_NETWORK_DRIVE);
+ return(FALSE);
+ }
+ }
+ else if (searchNumber = GetSearchNumber(inputPath))
+ {
+ int drive = GetDriveFromSearchNumber (searchNumber);
+
+ if (!drive)
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_SEARCH_DRIVE_NOT_EXIST, searchNumber);
+ return FALSE;
+ }
+
+ if (!IsNetwareDrive(drive))
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_NOT_NETWORK_DRIVE);
+ return(FALSE);
+ }
+
+ inputPath[0] = 'A' + drive - 1;
+ inputPath[1] = ':';
+ inputPath[2] = 0;
+ }
+
+ strcat (inputPath, directory);
+ }
+ else
+ {
+ if ( fNDS )
+ {
+ CHAR fullname[MAX_PATH];
+ if ( !NDSCanonicalizeName( mapPath, fullname, MAX_PATH, TRUE ) )
+ if ( !ConverNDSPathToNetWarePathA( fullname, DSCL_DIRECTORY_MAP,
+ inputPath ) )
+ goto ParseThePath;
+ }
+
+ // If drive is not specified, the current drive is used.
+ drive = _getdrive();
+ if (!IsNetwareDrive(drive))
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_NOT_NETWORK_DRIVE);
+ return(FALSE);
+ }
+
+ inputPath[0] = 'A'+drive-1;
+ inputPath[1] = ':';
+ inputPath[2] = 0;
+
+ strcat (inputPath, mapPath);
+ }
+
+ParseThePath:
+
+ iRet = ParsePath (inputPath,
+ serverName,
+ volName,
+ dirPath);
+ if (iRet)
+ {
+ if (iRet == 0x880F)
+ {
+ DisplayMessage(IDR_MAP_NOT_ATTACHED_SERVER, lpCommand);
+ return(FALSE);
+ }
+ else
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_INVALID_PATH, inputPath);
+ return(FALSE);
+ }
+ }
+
+ return(TRUE);
+}
+
+/*
+ Map drive to mapPath
+ */
+int MapDrive (int drive, int searchNum, char * mapPath, int bRoot, int bInsert, int fMapErrorsOn, char *lpCommand)
+{
+ unsigned int iRet=0;
+ char volName[MAX_VOLUME_LEN+1]; //+1 for append ':'.
+ char dirPath[MAX_DIR_PATH_LEN];
+ int currentDrive;
+ int OvermapDrive = -1;
+ char serverName[MAX_NAME_LEN];
+
+ if (!ParseMapPath(mapPath, volName, dirPath, serverName, fMapErrorsOn, lpCommand))
+ return(3);
+
+ if (IsNetwareDrive(drive))
+ {
+ if ( drive == _getdrive() ) {
+ OvermapDrive = drive;
+ _chdrive (SafeDisk);
+ }
+ if (iRet = DeleteDriveBase ((unsigned short)drive))
+ {
+ if (fMapErrorsOn) {
+ /* Cannot delete the drive you are on */
+ if (iRet == ERROR_DEVICE_IN_USE)
+ DisplayMessage(IDR_CAN_NOT_CHANGE_DRIVE);
+ else
+ DisplayError (iRet, "DeleteDriveBase");
+ }
+ return iRet;
+ }
+ }
+ else if ( IsNonNetwareNetworkDrive(drive) ) {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_NON_NETWARE_NETWORK_DRIVE, lpCommand);
+ return 3;
+ }
+
+ if (bRoot)
+ {
+ // +2 is for strcat with ":".
+ char *fullPath = malloc( MAX_VOLUME_LEN + strlen (dirPath) + 2);
+ if (fullPath == NULL)
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return 8;
+ }
+
+ strcpy (fullPath, volName);
+ strcat (fullPath, ":");
+ strcat (fullPath, dirPath);
+
+ iRet = SetDriveBase ((unsigned short)drive,
+ serverName,
+ 0,
+ fullPath);
+
+ // Relative names need to be expanded for the redirector
+
+ if ( iRet && fNDS && ( volName[strlen(volName) - 1] == '.' ) )
+ {
+ char canonName[MAX_VOLUME_LEN+1];
+ if ( !NDSCanonicalizeName( volName, canonName, MAX_VOLUME_LEN, TRUE ) )
+ {
+ strcpy (fullPath, canonName);
+ strcat (fullPath, ":");
+ strcat (fullPath, dirPath);
+
+ iRet = SetDriveBase ((unsigned short)drive,
+ serverName,
+ 0,
+ fullPath);
+ }
+ }
+
+ if (iRet == 0)
+ {
+ if (searchNum)
+ searchNum = InsertSearchDrive(searchNum, drive, bInsert, NULL);
+
+ currentDrive = _getdrive();
+ _chdrive (drive);
+ _chdir( "\\" );
+ _chdrive (currentDrive);
+ ExportCurrentDirectory( drive );
+
+ if (fMapDisplayOn)
+ {
+ if (searchNum)
+ DisplaySearchDriveMapping (searchNum);
+ else
+ DisplayDriveMapping((unsigned short)drive);
+ }
+ }
+ else
+ {
+ if (fMapErrorsOn)
+ {
+ switch ( iRet )
+ {
+ case ERROR_DEVICE_IN_USE:
+ DisplayMessage(IDR_CAN_NOT_CHANGE_DRIVE);
+ break;
+ case ERROR_BAD_NETPATH:
+ case ERROR_BAD_NET_NAME:
+ DisplayMessage(IDR_VOLUME_NOT_EXIST, volName);
+ iRet = 3;
+ break;
+ case ERROR_EXTENDED_ERROR:
+ NTPrintExtendedError();
+ iRet = 3;
+ break;
+ default:
+ DisplayMessage(IDR_MAP_ERROR, iRet);
+ DisplayMessage(IDR_MAP_FAILED, lpCommand);
+ iRet = 3;
+ break;
+ }
+ }
+ }
+
+ free (fullPath);
+ }
+ else
+ {
+ // NETX requires to end the volName with ':'.
+ strcat (volName, ":");
+
+ iRet = SetDriveBase ((unsigned short)drive,
+ serverName,
+ 0,
+ volName);
+
+ // Relative names need to be expanded for the redirector
+
+ if ( iRet && fNDS && ( volName[strlen(volName) - 2] == '.' ) )
+ {
+ char canonName[MAX_VOLUME_LEN+1];
+
+ volName[strlen(volName)-1] = '\0';
+ if ( !NDSCanonicalizeName( volName, canonName, MAX_VOLUME_LEN, TRUE ) )
+ {
+ strcat (canonName, ":");
+
+ iRet = SetDriveBase ((unsigned short)drive,
+ serverName,
+ 0,
+ canonName);
+ }
+ }
+
+ if (iRet)
+ {
+ if (fMapErrorsOn)
+ {
+ switch ( iRet )
+ {
+ case ERROR_DEVICE_IN_USE:
+ DisplayMessage(IDR_CAN_NOT_CHANGE_DRIVE);
+ break;
+ case ERROR_EXTENDED_ERROR:
+ NTPrintExtendedError();
+ iRet = 3;
+ break;
+ case ERROR_BAD_NETPATH:
+ case ERROR_BAD_NET_NAME:
+ default:
+ DisplayMessage(IDR_MAP_INVALID_PATH, lpCommand);
+ iRet = 3;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Succeed.
+
+ if (searchNum)
+ searchNum = InsertSearchDrive(searchNum, drive, bInsert, NULL);
+
+ currentDrive = _getdrive();
+ _chdrive (drive);
+ if (!iRet && *dirPath)
+ {
+ iRet = _chdir( "\\" );
+ if ( !iRet )
+ iRet = _chdir (dirPath);
+ if ( iRet ) {
+ if (fMapErrorsOn)
+ {
+ DisplayMessage(IDR_MAP_INVALID_PATH, lpCommand);
+ }
+
+ iRet = 3;
+ }
+
+ }
+ else
+ {
+ _chdir( "\\" );
+ }
+ _chdrive (currentDrive);
+ ExportCurrentDirectory( drive );
+
+ if (iRet == 0 && fMapDisplayOn)
+ {
+ if (searchNum)
+ DisplaySearchDriveMapping (searchNum);
+ else
+ DisplayDriveMapping((unsigned short)drive);
+ }
+
+ }
+ }
+
+ if ( OvermapDrive != -1 )
+ _chdrive (OvermapDrive);
+
+ return(iRet);
+}
+
+/*
+ Map drive secified by driveNum to mapPath.
+ If bRoot is TRUE, use mapPath as the drive base.
+ */
+int MapNonSearchDrive (int driveNum, char *mapPath, int bRoot, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand)
+{
+ int driveLetter, iRet = 0;
+
+ if ((driveNum == 0) && (!strchr(mapPath, ':') && !bRoot))
+ {
+ // map current drive to different directory.
+ if (_chdir(mapPath) && fMapErrorsOn)
+ {
+ DisplayMessage(IDR_DIRECTORY_NOT_FOUND, mapPath);
+ iRet = 3;
+ }
+ else {
+ ExportCurrentDirectory( _getdrive() );
+ if (fMapDisplayOn)
+ DisplayDriveMapping((unsigned short)driveNum);
+ }
+ return(iRet);
+ }
+ else if ( (driveNum) && (isalpha(mapPath[0]) && (mapPath[1] == ':')))
+ {
+ int mapdriveNum = toupper(mapPath[0]) - 'A' + 1;
+
+ if ( driveNum == mapdriveNum )
+ {
+ // map drive to different directory.
+ // map k:=k:\dir
+
+ WORD currentDrive;
+ currentDrive = _getdrive();
+ _chdrive (driveNum);
+ if (_chdir(mapPath) && fMapErrorsOn)
+ {
+ DisplayMessage(IDR_DIRECTORY_NOT_FOUND, mapPath);
+ iRet = 3;
+ }
+ else
+ {
+ ExportCurrentDirectory( _getdrive() );
+ if (fMapDisplayOn)
+ DisplayDriveMapping((unsigned short)driveNum);
+ }
+ _chdrive (currentDrive);
+ return(iRet);
+ }
+ }
+
+ if (driveNum == 0)
+ driveNum = _getdrive();
+
+ driveLetter = 'A' + driveNum -1;
+
+ return MapDrive (driveNum, 0, mapPath, bRoot, 0, fMapErrorsOn, lpCommand);
+}
+
+/*
+ Map the last free drive to mapPath and put it in the search path.
+ If bInsert is TRUE, don't replace search drive n, otherwise,
+ replace.
+ If bRoot is TRUE, use mapPath as the drive base.
+ */
+int MapSearchDrive (int searchNum, int driveNum, char *mapPath, int bInsert, int bRoot, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand)
+{
+ unsigned int iRet=0;
+ int i;
+ WORD status;
+ char * lpEqual;
+
+ /*
+ * Handle syntax map s2:=w:=volume:
+ * Handle syntax map w:=s2:=volume:
+ */
+ if ( driveNum )
+ {
+ return MapDrive (driveNum, searchNum, mapPath, bRoot, bInsert, fMapErrorsOn, lpCommand);
+ }
+
+ // Check if mapPath is local path.
+ if (mapPath[1] == ':' &&
+ IsLocalDrive (toupper(mapPath[0])-'A'+1))
+ {
+ i = 0; // a bug?
+ searchNum = InsertSearchDrive(searchNum, i, bInsert, mapPath);
+ if ((searchNum != 0) && fMapDisplayOn)
+ DisplayMessage(IDR_LOCAL_SEARCH, searchNum, mapPath);
+ return 0;
+ }
+
+ // Try to find the last available drive.
+ for (i = 26; i >= 1; i--)
+ {
+ iRet = GetDriveStatus ((unsigned short)i,
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (iRet)
+ continue;
+
+ if (!(status & NETWARE_LOCAL_DRIVE) &&
+ !(status & NETWARE_NETWORK_DRIVE))
+ {
+ // Found. Map it to the path.
+ return MapDrive (i, searchNum, mapPath, bRoot, bInsert, fMapErrorsOn, lpCommand);
+ }
+ }
+
+ if (fMapErrorsOn)
+ DisplayMessage (IDR_NO_DRIVE_AVAIL);
+ return(0);
+}
+
+/*
+ Map the next available drive to the mapPath.
+ */
+int MapNextAvailableDrive (char *mapPath, int fMapDisplayOn, int fMapErrorsOn, char *lpCommand)
+{
+ unsigned int iRet = 0;
+ int i;
+ WORD status;
+
+ // Find a free drive that is not mapped.
+ // Then map it to the mapPath.
+ for (i = 1; i <= 26; i++)
+ {
+ iRet = GetDriveStatus ((unsigned short)i,
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (iRet)
+ {
+ if (fMapErrorsOn)
+ DisplayError (iRet, "GetDriveStatus");
+ return iRet;
+ }
+
+ if (!(status & NETWARE_LOCAL_DRIVE) &&
+ !(status & NETWARE_NETWORK_DRIVE))
+ {
+ iRet = MapNonSearchDrive (i, mapPath, FALSE, fMapDisplayOn, fMapErrorsOn, lpCommand);
+ return iRet;
+ }
+ }
+
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_NO_DRIVE_AVAIL);
+
+ return(0);
+}
+
+/*
+ Remove a drive mapping.
+ */
+int RemoveDrive (WORD drive, int fMapDisplayOn, int fMapErrorsOn)
+{
+ unsigned int iRet=0;
+ int searchNum;
+
+ if (IsNetwareDrive (drive))
+ {
+ if (searchNum = IsSearchDrive(drive))
+ {
+ RemoveSearchDrive (searchNum, fMapDisplayOn, fMapErrorsOn);
+ }
+ else
+ {
+ /*
+ * Can't delete current drive on NT
+ */
+ if ( drive == _getdrive() ) {
+ _chdrive (SafeDisk);
+ }
+ if (iRet = DeleteDriveBase (drive))
+ {
+ if (fMapErrorsOn)
+ DisplayError (iRet, "DeleteDriveBase");
+ }
+ else
+ {
+ if (fMapDisplayOn)
+ DisplayMessage(IDR_DEL_DRIVE, 'A'+drive-1);
+ }
+ }
+ }
+ else
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_WRONG_DRIVE, 'A'+drive-1);
+
+ return(50); //error level.
+ }
+
+ return(0);
+}
+
+/*
+ Remove a search drive.
+ */
+void RemoveSearchDrive (int searchNumber, int fMapDisplayOn, int fMapErrorsOn)
+{
+ WORD drive;
+
+ // Get the drive number.
+ drive = GetDriveFromSearchNumber (searchNumber);
+
+ if (!drive)
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_SEARCH_DRIVE_NOT_EXIST, searchNumber);
+ return;
+ }
+
+ // If the drive is a netware drive, remove the drive mapping.
+ if (IsNetwareDrive (drive))
+ {
+ unsigned int iRet=0;
+ /*
+ * Can't delete current drive on NT
+ */
+ if ( drive == _getdrive() ) {
+ _chdrive (SafeDisk);
+ }
+ if (iRet = DeleteDriveBase (drive))
+ {
+ if (fMapErrorsOn)
+ DisplayError (iRet, "DeleteDriveBase");
+ return;
+ }
+ }
+
+ RemoveDriveFromPath (searchNumber, fMapErrorsOn);
+
+ if (fMapDisplayOn)
+ DisplayMessage(IDR_DEL_SEARCH_DRIVE, 'A'+drive-1);
+
+ // If the drive is not a local drive, remove all reference
+ // to the drive in the path.
+ if (!IsLocalDrive (drive))
+ {
+ while (searchNumber = IsSearchDrive (drive))
+ {
+ RemoveDriveFromPath (searchNumber, fMapErrorsOn);
+ }
+ }
+}
+
+/*
+ Remove a search drive from the path.
+ */
+void RemoveDriveFromPath(int searchNumber, int fMapErrorsOn)
+{
+ char *pOldPath, *pNewPath, *restEnvSeg, *pPath, *Path;
+ int i, n;
+
+ // Move pOldPath to where we want to put the new path string.
+ pOldPath = NWGetPath();
+ pPath = malloc( strlen(pOldPath) + 5 + 1 + 1 );
+ strcpy(pPath, "PATH=");
+ strcat(pPath, pOldPath);
+ pOldPath = pPath + 5;
+
+ for (i = 1; i < searchNumber; i++)
+ {
+ pOldPath=strchr (pOldPath, ';');
+
+ if (pOldPath == NULL)
+ {
+ if (fMapErrorsOn)
+ DisplayMessage(IDR_SEARCH_DRIVE_NOT_EXIST, searchNumber);
+ free( pPath );
+ return;
+ }
+
+ pOldPath++;
+ }
+
+ // Move pNewPath to the beginning of the path string that
+ // needs to be moved.
+ if (pNewPath = strchr (pOldPath, ';'))
+ pNewPath++ ;
+ else
+ pNewPath = pOldPath + strlen (pOldPath);
+
+ // Calculate the number of characters needs to be moved.
+ n = strlen (pNewPath) + 1;
+ restEnvSeg = pNewPath + n;
+
+ n++;
+
+ // Move the path string to overwrite the search drive.
+ memmove (pOldPath, pNewPath, n);
+
+ Path = malloc (strlen (pPath)+1);
+ strcpy (Path, pPath);
+ _putenv (Path);
+ ExportEnv( pPath );
+ free( pPath );
+}
+
+
+/*
+ If bInsert is TRUE, insert dirve specified by driveNum as search
+ drive specified by searchNum. Otherwise replace search drive
+ specified by searchNum with drive specified by driveNum.
+ */
+int InsertSearchDrive(int searchNum, int driveNum, int bInsert, char * insertPath)
+{
+ char *pOldPath, *pNewPath, *restEnvSeg, *pPath, *Path;
+ int i, n = 0, bSemiColon, nInsertChar;
+
+ nInsertChar = (insertPath == NULL)? 3 : strlen (insertPath);
+
+ // Check if memory block is large enough.
+ if (!MemorySegmentLargeEnough (nInsertChar+1))
+ return 0;
+
+ // Move pNewPath to where we put the new drive.
+ pNewPath = NWGetPath();
+ pPath = malloc( strlen(pNewPath) + 5 + 1 + nInsertChar + 1 + 1 );
+ strcpy(pPath, "PATH=");
+ strcat(pPath, pNewPath);
+ pNewPath = pPath + 5;
+
+ for (i = 1; i < searchNum; i++)
+ {
+ if (strchr (pNewPath, ';'))
+ {
+ pNewPath = strchr (pNewPath, ';');
+ }
+ else
+ {
+ pNewPath += strlen (pNewPath);
+ bInsert = TRUE;
+ i++;
+ break;
+ }
+
+ pNewPath++;
+ }
+
+ // Move pOldPath to the begining of the path string that needs
+ // to be moved.
+ if (bInsert)
+ pOldPath = pNewPath;
+ else
+ {
+ if ((pOldPath = strchr (pNewPath, ';')) == NULL)
+ pOldPath = pNewPath + strlen (pNewPath);
+ else
+ pOldPath++;
+ }
+
+ // Figure out the number of characters that need to be moved.
+ n = strlen (pOldPath) + 1;
+ restEnvSeg = pOldPath + strlen (pOldPath) + 1;
+
+ n++;
+
+ // If we insert a new drive to the end of the path which ends with
+ // a ';', or if we replace the last search drive, no ';' is needed.
+ bSemiColon = bInsert ? (*(pNewPath-1) != ';' || *pOldPath != 0)
+ : (*pOldPath != 0);
+
+ // Move the old path so that we will have space for the new search drive.
+ memmove (pNewPath + (bSemiColon? nInsertChar+1:nInsertChar), pOldPath, n);
+
+ if ((*pNewPath == 0)&& bSemiColon)
+ {
+ // Insert as the last one to the path.
+ // Put ';' at the begining.
+ *pNewPath = ';';
+ if (insertPath == NULL)
+ {
+ *(pNewPath+1) = 'A' + driveNum - 1;
+ *(pNewPath+2) = ':';
+ *(pNewPath+3) = '.';
+ }
+ else
+ memcpy (pNewPath+1, insertPath, nInsertChar);
+ }
+ else
+ {
+ if (insertPath == NULL)
+ {
+ *pNewPath = 'A' + driveNum - 1;
+ *(pNewPath+1) = ':';
+ *(pNewPath+2) = '.';
+ }
+ else
+ memcpy (pNewPath, insertPath, nInsertChar);
+ if (bSemiColon)
+ *(pNewPath+nInsertChar) = ';';
+ }
+
+ Path = malloc (strlen (pPath)+1);
+ strcpy (Path, pPath);
+ _putenv (Path);
+ ExportEnv( pPath );
+ free( pPath );
+
+ return (i);
+}
+
+/*
+ * Used by SetEnv().
+ * Return the number of bytes of environment variable pointed by lpRest
+ */
+int GetRestEnvLen (char *lpRest)
+{
+ int nTotal = 1;
+ nTotal += strlen (lpRest);
+
+ return(nTotal);
+}