summaryrefslogtreecommitdiffstats
path: root/private/nw/nwscript
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/nw/nwscript
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/nw/nwscript')
-rw-r--r--private/nw/nwscript/attach.c235
-rw-r--r--private/nw/nwscript/break.c85
-rw-r--r--private/nw/nwscript/capture.c1067
-rw-r--r--private/nw/nwscript/common.c400
-rw-r--r--private/nw/nwscript/date.c78
-rw-r--r--private/nw/nwscript/dbcs.c98
-rw-r--r--private/nw/nwscript/display.c101
-rw-r--r--private/nw/nwscript/drive.c327
-rw-r--r--private/nw/nwscript/drvstat.c268
-rw-r--r--private/nw/nwscript/env.c352
-rw-r--r--private/nw/nwscript/helpers.c96
-rw-r--r--private/nw/nwscript/inc/common.h195
-rw-r--r--private/nw/nwscript/inc/dbcs.h26
-rw-r--r--private/nw/nwscript/inc/ntnw.h46
-rw-r--r--private/nw/nwscript/inc/nwlibs.h371
-rw-r--r--private/nw/nwscript/inc/nwscript.h321
-rw-r--r--private/nw/nwscript/lsparse.c315
-rw-r--r--private/nw/nwscript/makefile6
-rw-r--r--private/nw/nwscript/maplist.c252
-rw-r--r--private/nw/nwscript/ncp.c356
-rw-r--r--private/nw/nwscript/nds.c1505
-rw-r--r--private/nw/nwscript/nt.c617
-rw-r--r--private/nw/nwscript/ntcap.c329
-rw-r--r--private/nw/nwscript/ntnw.c163
-rw-r--r--private/nw/nwscript/ntscript.c304
-rw-r--r--private/nw/nwscript/nwapi1.c47
-rw-r--r--private/nw/nwscript/nwapi2.c49
-rw-r--r--private/nw/nwscript/nwapi3.c1457
-rw-r--r--private/nw/nwscript/nwscript.c84
-rw-r--r--private/nw/nwscript/nwscript.rc243
-rw-r--r--private/nw/nwscript/parspath.c341
-rw-r--r--private/nw/nwscript/ps40db.c597
-rw-r--r--private/nw/nwscript/psdb.c396
-rw-r--r--private/nw/nwscript/script.c3968
-rw-r--r--private/nw/nwscript/sources85
-rw-r--r--private/nw/nwscript/strings.c132
-rw-r--r--private/nw/nwscript/time.c184
-rw-r--r--private/nw/nwscript/unc.c142
-rw-r--r--private/nw/nwscript/version.c68
-rw-r--r--private/nw/nwscript/wide.c149
40 files changed, 15855 insertions, 0 deletions
diff --git a/private/nw/nwscript/attach.c b/private/nw/nwscript/attach.c
new file mode 100644
index 000000000..fa6cacc75
--- /dev/null
+++ b/private/nw/nwscript/attach.c
@@ -0,0 +1,235 @@
+/*************************************************************************
+*
+* ATTACH.C
+*
+* NT Attach routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\ATTACH.C $
+*
+* Rev 1.2 10 Apr 1996 14:21:30 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:52:08 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:23:32 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:26 terryt
+* Initial revision.
+*
+* Rev 1.1 23 May 1995 19:36:30 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:10:10 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <nwapi32.h>
+#include <ntddnwfs.h>
+#include <nwapi.h>
+#include <npapi.h>
+
+#include "inc/common.h"
+#include "ntnw.h"
+
+/********************************************************************
+
+ GetDefaultConnectionID
+
+Routine Description:
+
+ Return the default connection ID ( the "preferred server" )
+
+Arguments:
+
+ phNewConn - pointer to connection number
+
+Return Value:
+ 0 = success
+ else NetWare error number
+
+ *******************************************************************/
+unsigned int
+GetDefaultConnectionID(
+ unsigned int *phNewConn
+ )
+{
+ VERSION_INFO VerInfo;
+ unsigned int Result;
+
+ if ( fNDS )
+ {
+ Result = NTAttachToFileServer( NDSTREE, phNewConn );
+ }
+ else
+ {
+ //
+ // "*" is the name for the preferred server
+ //
+ Result = NTAttachToFileServer( "*", phNewConn );
+ if ( Result )
+ return Result;
+
+ Result = NWGetFileServerVersionInfo( (NWCONN_HANDLE)*phNewConn,
+ &VerInfo );
+ if ( Result )
+ return Result;
+
+ NWDetachFromFileServer( (NWCONN_HANDLE)*phNewConn );
+
+ Result = NTAttachToFileServer( VerInfo.szName, phNewConn );
+ }
+ return Result;
+
+}
+
+/********************************************************************
+
+ NTAttachToFileServer
+
+Routine Description:
+
+ Given a server name, return a connection handle.
+ We need our own because NWAPI32 does it's own mapping
+ of errors.
+
+Arguments:
+
+ pszServerName - Ascii server name
+ phNewConn - pointer to connection handle
+
+Return Value:
+ 0 = success
+ else NetWare error number
+
+ *******************************************************************/
+unsigned int
+NTAttachToFileServer(
+ unsigned char *pszServerName,
+ unsigned int *phNewConn
+ )
+{
+ return ( NWAttachToFileServer( pszServerName, 0,
+ (NWCONN_HANDLE *)phNewConn ) );
+}
+
+
+/********************************************************************
+
+ NTIsConnected
+
+Routine Description:
+
+ Given a server name, is there already a connection to it?
+
+Arguments:
+
+ pszServerName - ascii server name
+
+Return Value:
+ TRUE - a connection to the server exists
+ FALSE - a connection to the server does not exist
+
+ *******************************************************************/
+unsigned int
+NTIsConnected( unsigned char * pszServerName )
+{
+ LPBYTE Buffer ;
+ DWORD dwErr ;
+ HANDLE EnumHandle ;
+ DWORD Count ;
+ LPWSTR pszServerNameW;
+ INT nSize;
+ DWORD BufferSize = 4096;
+
+ nSize = (strlen( pszServerName ) + 1 + 2) * sizeof( WCHAR );
+
+ //
+ // allocate memory and open the enumeration
+ //
+ if (!(pszServerNameW = LocalAlloc( LPTR, nSize ))) {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ wcscpy( pszServerNameW, L"\\\\" );
+ szToWide( pszServerNameW + 2, pszServerName, nSize );
+
+ //
+ // allocate memory and open the enumeration
+ //
+ if (!(Buffer = LocalAlloc( LPTR, BufferSize ))) {
+ (void) LocalFree((HLOCAL) pszServerNameW) ;
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ memset( Buffer, 0, BufferSize );
+
+ dwErr = NPOpenEnum(RESOURCE_CONNECTED, 0, 0, NULL, &EnumHandle) ;
+ if (dwErr != WN_SUCCESS) {
+ (void) LocalFree((HLOCAL) pszServerNameW) ;
+ (void) LocalFree((HLOCAL) Buffer) ;
+ return FALSE;
+ }
+
+ do {
+
+ Count = 0xFFFFFFFF ;
+ BufferSize = 4096;
+ dwErr = NwEnumConnections(EnumHandle, &Count, Buffer, &BufferSize, TRUE) ;
+
+ if ((dwErr == WN_SUCCESS || dwErr == WN_NO_MORE_ENTRIES)
+ && ( Count != 0xFFFFFFFF) )
+ {
+ LPNETRESOURCE lpNetResource ;
+ DWORD i ;
+ DWORD ServerLen;
+
+ ServerLen = wcslen( pszServerNameW );
+ lpNetResource = (LPNETRESOURCE) Buffer ;
+ //
+ // search for our server
+ //
+ for ( i = 0; i < Count; lpNetResource++, i++ )
+ {
+ if ( lpNetResource->lpProvider )
+ if ( _wcsicmp( lpNetResource->lpProvider, NW_PROVIDER ) ) {
+ continue;
+ }
+ if ( lpNetResource->lpRemoteName ) {
+ if ( wcslen(lpNetResource->lpRemoteName) > ServerLen ) {
+ if ( lpNetResource->lpRemoteName[ServerLen] == L'\\' )
+ lpNetResource->lpRemoteName[ServerLen] = L'\0';
+ }
+ if ( !_wcsicmp(lpNetResource->lpRemoteName, pszServerNameW )) {
+ (void) WNetCloseEnum(EnumHandle) ;
+ (void) LocalFree((HLOCAL) pszServerNameW) ;
+ (void) LocalFree((HLOCAL) Buffer) ;
+ return TRUE;
+ }
+ }
+ }
+
+ }
+
+ } while (dwErr == WN_SUCCESS) ;
+
+ (void ) WNetCloseEnum(EnumHandle) ;
+ (void) LocalFree((HLOCAL) pszServerNameW) ;
+ (void) LocalFree((HLOCAL) Buffer) ;
+
+ return FALSE;
+}
diff --git a/private/nw/nwscript/break.c b/private/nw/nwscript/break.c
new file mode 100644
index 000000000..30af584db
--- /dev/null
+++ b/private/nw/nwscript/break.c
@@ -0,0 +1,85 @@
+/*************************************************************************
+*
+* BREAK.C
+*
+* Control-C and Control-Break routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\BREAK.C $
+*
+* Rev 1.2 10 Apr 1996 14:21:38 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:52:16 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:23:38 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:28 terryt
+* Initial revision.
+*
+* Rev 1.0 15 May 1995 19:10:14 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "nwscript.h"
+#include "ntnw.h"
+
+
+/*
+ * Handler for console events
+ */
+BOOL WINAPI
+Handler( DWORD CtrlType )
+{
+ if ( CtrlType & ( CTRL_C_EVENT | CTRL_BREAK_EVENT ) )
+ return TRUE; /* don't execute default handler */
+}
+
+/*
+ * NTBreakOn
+ *
+ * Routine Description:
+ *
+ * Allow Ctrl+C and Ctrl+Break during logon script
+ *
+ * Arguments:
+ * none
+ *
+ * Return Value:
+ * none
+ */
+void NTBreakOn( void )
+{
+ (void) SetConsoleCtrlHandler( &Handler, FALSE );
+}
+
+/*
+ * NTBreakOff
+ *
+ * Routine Description:
+ *
+ * Prevent Ctrl+C and Ctrl+Break during logon script
+ *
+ * Arguments:
+ * none
+ *
+ * Return Value:
+ * none
+ */
+void NTBreakOff( void )
+{
+ (void) SetConsoleCtrlHandler( &Handler, TRUE );
+}
diff --git a/private/nw/nwscript/capture.c b/private/nw/nwscript/capture.c
new file mode 100644
index 000000000..b89df1480
--- /dev/null
+++ b/private/nw/nwscript/capture.c
@@ -0,0 +1,1067 @@
+/*
+ * Module Name:
+ * capture.c
+ * Copyright (c) 1995 Microsoft Corporation
+ *
+ * Abstract:
+ *
+ * SYNTAX (Command line)
+ * - Usage: Capture [/Options]
+ *
+ * Author : Congpa You (Congpay)
+ *
+ * Revision history :
+ * - 05/24/94 congpay Created
+ */
+
+#include "common.h"
+
+extern char *RemoveSpaces (char * buffer);
+
+typedef struct _CAPTURE_PARAMS {
+ UCHAR nLPT;
+ char serverName[MAX_NAME_LEN];
+ char queueName[MAX_QUEUE_NAME_LEN];
+ char bannerUserName[MAX_BANNER_USER_NAME];
+ char filePath[_MAX_PATH];
+ unsigned int NDSCapture;
+ NETWARE_CAPTURE_FLAGS_RW captureFlagsRW;
+}CAPTURE_PARAMS, *PCAPTURE_PARAMS;
+
+/* Local Functions*/
+void UpcaseArg(int argc, char ** argv);
+int IsShowOption (int argc, char ** argv);
+int IsServerSpecified (int argc, char ** argv);
+int IsNoOption (char * option);
+int IsQuestionMark (int argc, char ** argv);
+int IsValidOption (char *input, char *option, char *shortoption);
+void ShowCapture(void);
+
+void GetJobNameFromArg (int argc, char ** argv, char *jobName);
+
+int InitCaptureParams (unsigned int conn,
+ char *jobName,
+ PCAPTURE_PARAMS pCaptureParams);
+
+int ReadArguments (int argc,
+ char ** argv,
+ char *jobName,
+ PCAPTURE_PARAMS pCaptureParams);
+
+int CStartCapture(unsigned int conn,
+ PCAPTURE_PARAMS pCaptureParams);
+
+int GetPrinterDefaultQueue( PCAPTURE_PARAMS, PBYTE );
+
+void
+Capture (char ** argv, unsigned int argc)
+{
+ char jobName[MAX_JOB_NAME_LEN]="";
+ CAPTURE_PARAMS captureParams;
+ unsigned int conn;
+
+ UpcaseArg(argc, argv);
+
+ memset( (PBYTE)&captureParams, 0, sizeof(captureParams) );
+
+ captureParams.nLPT = 0;
+ captureParams.serverName[0] = 0;
+ captureParams.queueName[0] = 0;
+ captureParams.bannerUserName[0] = 0;
+ captureParams.filePath[0] = 0;
+
+ if ( fNDS )
+ {
+ captureParams.NDSCapture = TRUE;
+ }
+ else
+ {
+ captureParams.NDSCapture = FALSE;
+ }
+
+ if ( IsServerSpecified( argc, argv ) )
+ captureParams.NDSCapture = FALSE;
+
+ // If the option is show, show the current capture settings.
+ if (IsShowOption (argc, argv))
+ {
+ ShowCapture();
+ return;
+ }
+
+ // If the option is ?, show the usage.
+ if (IsQuestionMark(argc, argv))
+ {
+ DisplayMessage(IDR_CAPTURE_USAGE);
+ return;
+ }
+
+ // If /Job=jobname is in the parameter, get the jobname.
+ GetJobNameFromArg (argc, argv, jobName);
+
+ if (!CGetDefaultConnectionID (&conn) ||
+ !InitCaptureParams (conn, jobName, &captureParams) ||
+ !ReadArguments (argc,
+ argv,
+ jobName,
+ &captureParams))
+ return;
+
+ // Terminate old capture.
+ EndCapture ((unsigned char) captureParams.nLPT);
+
+ (void) CStartCapture(conn, &captureParams);
+ return;
+}
+
+void UpcaseArg(int argc, char ** argv)
+{
+ int i;
+ for (i = 0; i < argc ; i++)
+ _strupr (argv[i]);
+}
+
+/*
+ Return TRUE if input is /Show option.
+ FALSE otherwise.
+ */
+int IsShowOption (int argc,char ** argv)
+{
+ int bIsShowOption = FALSE;
+ char * p;
+
+ if (argc == 2)
+ {
+ p = argv[1];
+ while ((*p == '/') || (*p == '\\') || (*p == '-'))
+ p++;
+
+ if (!strncmp (p, __SHOW__, max (2, strlen(p))))
+ bIsShowOption = TRUE;
+ }
+
+ return(bIsShowOption);
+}
+
+/*
+ Return TRUE if input is /? option.
+ FALSE otherwise.
+ */
+int IsQuestionMark (int argc, char ** argv)
+{
+ int bIsQuestionMark = FALSE;
+ char * p;
+
+ if (argc == 2)
+ {
+ p = argv[1];
+ while ((*p == '/') || (*p == '\\') || (*p == '-'))
+ p++;
+
+ if (*p == '?')
+ bIsQuestionMark = TRUE;
+ }
+
+ return(bIsQuestionMark);
+}
+
+int IsNoOption (char * option)
+{
+ int bIsNoOption = FALSE;
+ char * p;
+
+ p = option;
+ while ((*p == '/') || (*p == '\\') || (*p == '-'))
+ p++;
+
+ if (!strncmp (p, __OPT_NO__, max (1, strlen(p))))
+ bIsNoOption = TRUE;
+
+ return(bIsNoOption);
+}
+
+/*
+ Return TRUE if the input match option or shortoption.
+ FALSE otherwise.
+ */
+int IsValidOption (char *input, char *option, char *shortoption)
+{
+ int bValideInput = FALSE;
+
+ while ((*input == '/') || (*input == '\\') || (*input == '-'))
+ input++;
+
+ if (!strcmp (input, shortoption))
+ {
+ bValideInput = TRUE;
+ }
+ else if (!strcmp (input, option))
+ {
+ bValideInput = TRUE;
+ }
+
+ return(bValideInput);
+}
+
+void GetJobNameFromArg (int argc, char ** argv, char *jobName)
+{
+ int i;
+ char *pEqual;
+
+ for (i = 0; i < argc; i++)
+ {
+ if (pEqual = strchr (argv[i], '='))
+ {
+ *pEqual = 0;
+
+ if (IsValidOption (argv[i], __JOB__, __SHORT_FOR_JOB__) &&
+ *(pEqual+1) != 0 &&
+ strlen (pEqual+1) < MAX_JOB_NAME_LEN)
+ strcpy (jobName, pEqual+1);
+
+ *pEqual = '=';
+ }
+ }
+
+ return;
+}
+
+int IsServerSpecified (int argc, char ** argv)
+{
+ int i;
+
+ for (i = 0; i < argc; i++)
+ {
+ if (IsValidOption (argv[i], __SERVER__, __SHORT_FOR_SERVER__))
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+/*
+ Initialize the capture flags with job config or default value.
+ */
+int InitCaptureParams (unsigned int conn,
+ char *jobName,
+ PCAPTURE_PARAMS pCaptureParams)
+{
+ PS_JOB_RECORD psJobRecord;
+ unsigned int iRet = 0;
+
+ // Get job configuration.
+ if (jobName[0] == 0)
+ {
+ // Get Default Job Name.
+ if ( Is40Server( conn ) )
+ {
+ iRet = PS40JobGetDefault( pCaptureParams->NDSCapture,
+ 0,
+ NULL,
+ jobName,
+ &psJobRecord );
+ }
+ else
+ {
+ iRet = PSJobGetDefault( conn,
+ 0,
+ NULL,
+ jobName,
+ &psJobRecord );
+ }
+
+ if ( iRet )
+ {
+ if (iRet == PS_ERR_OPENING_DB || iRet == PS_ERR_GETTING_DEFAULT)
+ {
+ pCaptureParams->nLPT = 1;
+ pCaptureParams->bannerUserName[0]=0;
+ pCaptureParams->serverName[0]=0;
+ pCaptureParams->queueName[0]=0;
+ pCaptureParams->filePath[0]=0;
+
+ pCaptureParams->captureFlagsRW.JobControlFlags = 0;
+ pCaptureParams->captureFlagsRW.TabSize = 8;
+ pCaptureParams->captureFlagsRW.NumCopies = 1;
+ pCaptureParams->captureFlagsRW.PrintFlags = DEFAULT_PRINT_FLAGS;
+ pCaptureParams->captureFlagsRW.FormName[0] = 0;
+ pCaptureParams->captureFlagsRW.FormType = 0;
+ pCaptureParams->captureFlagsRW.FlushCaptureTimeout = 0;
+ pCaptureParams->captureFlagsRW.FlushCaptureOnClose = 0;
+
+ strcpy (pCaptureParams->captureFlagsRW.BannerText, DEFAULT_BANNER_TEXT);
+ return(TRUE);
+ }
+ else
+ {
+ DisplayError (iRet, "PSJobGetDefault");
+ return(FALSE);
+ }
+ }
+ }
+ else
+ {
+ if ( Is40Server( conn ) )
+ {
+ iRet = PS40JobRead( pCaptureParams->NDSCapture,
+ NULL,
+ jobName,
+ &psJobRecord);
+ }
+ else
+ {
+ iRet = PSJobRead(conn,
+ NULL,
+ jobName,
+ &psJobRecord);
+ }
+ if ( iRet )
+ {
+ if ( ( iRet == PS_ERR_READING_RECORD) ||
+ ( iRet == PS_ERR_OPENING_DB) )
+ DisplayMessage(IDR_JOB_NOT_FOUND, jobName);
+ else
+ DisplayError (iRet, "PSJobRead");
+ return(FALSE);
+ }
+ }
+
+ pCaptureParams->captureFlagsRW.JobControlFlags = 0;
+ pCaptureParams->captureFlagsRW.TabSize = psJobRecord.TabSize;
+ pCaptureParams->captureFlagsRW.NumCopies = psJobRecord.Copies;
+
+ pCaptureParams->captureFlagsRW.PrintFlags =
+ ((psJobRecord.PrintJobFlag & PS_JOB_EXPAND_TABS)? 0 : CAPTURE_FLAG_EXPAND_TABS)
+ +((psJobRecord.PrintJobFlag & PS_JOB_NO_FORMFEED)? CAPTURE_FLAG_NO_FORMFEED : 0)
+ +((psJobRecord.PrintJobFlag & PS_JOB_NOTIFY)? CAPTURE_FLAG_NOTIFY : 0)
+ +((psJobRecord.PrintJobFlag & PS_JOB_PRINT_BANNER)? CAPTURE_FLAG_PRINT_BANNER : 0);
+
+ pCaptureParams->captureFlagsRW.FormType = 0;
+ pCaptureParams->captureFlagsRW.FlushCaptureTimeout = psJobRecord.TimeOutCount;
+ pCaptureParams->captureFlagsRW.FlushCaptureOnClose = !(psJobRecord.PrintJobFlag & PS_JOB_AUTO_END);
+
+ strcpy (pCaptureParams->captureFlagsRW.FormName, psJobRecord.FormName);
+ strcpy (pCaptureParams->captureFlagsRW.BannerText, (psJobRecord.BannerName[0] == 0)? DEFAULT_BANNER_TEXT : psJobRecord.BannerName);
+
+ pCaptureParams->nLPT = psJobRecord.LocalPrinter;
+ strcpy (pCaptureParams->bannerUserName, psJobRecord.Name);
+ if ( psJobRecord.PrintJobFlag & PS_JOB_ENV_DS ) {
+ strcpy (pCaptureParams->serverName, "");
+ if ( psJobRecord.PrintJobFlag & PS_JOB_DS_PRINTER )
+ GetPrinterDefaultQueue( pCaptureParams, psJobRecord.u.DSObjectName );
+ else
+ strcpy (pCaptureParams->queueName, psJobRecord.u.DSObjectName );
+ }
+ else {
+ strcpy (pCaptureParams->serverName, psJobRecord.u.NonDS.FileServer);
+ strcpy (pCaptureParams->queueName, psJobRecord.u.NonDS.PrintQueue);
+ }
+ pCaptureParams->filePath[0]=0;
+
+ return(TRUE);
+}
+
+int ReadArguments (int argc,
+ char ** argv,
+ char *jobName,
+ PCAPTURE_PARAMS pCaptureParams)
+{
+ int i, fValidOption = TRUE, fValidParam = TRUE;
+ char *pEqual = NULL;
+
+ for (i = 1; i < argc; i++)
+ {
+ if (IsNoOption(argv[i]))
+ {
+ if (i != argc - 1)
+ {
+ i++;
+
+ if (IsValidOption (argv[i], __NOTIFY__, __SHORT_FOR_NOTIFY__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags &= (0xFF-CAPTURE_FLAG_NOTIFY);
+ }
+ else if (IsValidOption (argv[i], __AUTOENDCAP__, __SHORT_FOR_AUTOENDCAP__))
+ {
+ pCaptureParams->captureFlagsRW.FlushCaptureOnClose = 1;
+ }
+ else if (IsValidOption (argv[i], __TABS__, __SHORT_FOR_TABS__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags &= (0xFF - CAPTURE_FLAG_EXPAND_TABS);
+ }
+ else if (IsValidOption (argv[i], __BANNER__, __SHORT_FOR_BANNER__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags &= (0xFF - CAPTURE_FLAG_PRINT_BANNER);
+ }
+ else if (IsValidOption (argv[i], __FORMFEED__, __SHORT_FOR_FORMFEED__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags |= CAPTURE_FLAG_NO_FORMFEED;
+ }
+ else
+ {
+ i--;
+ fValidOption = FALSE;
+ break;
+ }
+ }
+ else
+ {
+ fValidOption = FALSE;
+ break;
+ }
+ }
+ else if (IsValidOption (argv[i], __NOTIFY__, __SHORT_FOR_NOTIFY__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags |= CAPTURE_FLAG_NOTIFY;
+ }
+ else if (IsValidOption (argv[i], __NONOTIFY__, __SHORT_FOR_NONOTIFY__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags &= (0xFF - CAPTURE_FLAG_NOTIFY);
+ }
+ else if (IsValidOption (argv[i], __AUTOENDCAP__, __SHORT_FOR_AUTOENDCAP__))
+ {
+ pCaptureParams->captureFlagsRW.FlushCaptureOnClose = 0;
+ }
+ else if (IsValidOption (argv[i], __NOAUTOENDCAP__, __SHORT_FOR_NOAUTOENDCAP__))
+ {
+ pCaptureParams->captureFlagsRW.FlushCaptureOnClose = 1;
+ }
+ else if (IsValidOption (argv[i], __NOTABS__, __SHORT_FOR_NOTABS__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags &= (0xFF - CAPTURE_FLAG_EXPAND_TABS);
+ }
+ else if (IsValidOption (argv[i], __NOBANNER__, __SHORT_FOR_NOBANNER__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags &= (0xFF - CAPTURE_FLAG_PRINT_BANNER);
+ }
+ else if (IsValidOption (argv[i], __FORMFEED__, __SHORT_FOR_FORMFEED__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags &= (0xFF - CAPTURE_FLAG_NO_FORMFEED);
+ }
+ else if (IsValidOption (argv[i], __NOFORMFEED__, __SHORT_FOR_NOFORMFEED__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags |= CAPTURE_FLAG_NO_FORMFEED;
+ }
+ else if (IsValidOption (argv[i], __KEEP__, __SHORT_FOR_KEEP__))
+ {
+ pCaptureParams->captureFlagsRW.PrintFlags |= CAPTURE_FLAG_KEEP;
+ }
+ else
+ {
+ // All other valid options should have '=' sign in it.
+ // Except for LX LPX LPTX
+ //
+ pEqual = strchr (argv[i], '=');
+
+ // Optionally a ':' works too
+ if (pEqual == NULL ) {
+ pEqual = strchr (argv[i], ':');
+ }
+
+ if (pEqual != NULL)
+ *pEqual = 0;
+
+ if (IsValidOption (argv[i], __TIMEOUT__, __SHORT_FOR_TIMEOUT__))
+ {
+ if (pEqual == NULL || *(pEqual+1) == 0)
+ {
+ DisplayMessage(IDR_TIME_OUT_EXPECTED);
+ fValidParam = FALSE;
+ break;
+ }
+
+ pCaptureParams->captureFlagsRW.FlushCaptureTimeout = atoi (pEqual+1);
+
+ if (pCaptureParams->captureFlagsRW.FlushCaptureTimeout > 1000)
+ {
+ DisplayMessage(IDR_TIMEOUT_OUTOF_RANGE);
+ fValidParam = FALSE;
+ break;
+ }
+ }
+ else if (IsValidOption (argv[i], __LOCAL__, __SHORT_FOR_LOCAL__))
+ {
+ if (pEqual == NULL || *(pEqual+1) == 0)
+ {
+ DisplayMessage(IDR_LPT_NUMBER_EXPECTED);
+ fValidParam = FALSE;
+ break;
+ }
+
+ pCaptureParams->nLPT = (unsigned char) atoi (pEqual+1);
+
+ if (pCaptureParams->nLPT < 1 || pCaptureParams->nLPT > 3)
+ {
+ DisplayMessage(IDR_INVALID_LPT_NUMBER);
+ fValidParam = FALSE;
+ break;
+ }
+ }
+ else if (IsValidOption (argv[i], __LOCAL_3__, __LOCAL_2__))
+ {
+ if (pEqual == NULL || *(pEqual+1) == 0)
+ {
+ DisplayMessage(IDR_LPT_NUMBER_EXPECTED);
+ fValidParam = FALSE;
+ break;
+ }
+
+ pCaptureParams->nLPT = (unsigned char) atoi (pEqual+1);
+
+ if (pCaptureParams->nLPT < 1 || pCaptureParams->nLPT > 3)
+ {
+ DisplayMessage(IDR_INVALID_LPT_NUMBER);
+ fValidParam = FALSE;
+ break;
+ }
+ }
+ else if (IsValidOption (argv[i], __JOB__, __SHORT_FOR_JOB__))
+ {
+ if (pEqual == NULL ||
+ *(pEqual+1) == 0 ||
+ strlen (pEqual+1) > MAX_JOB_NAME_LEN - 1)
+ {
+ fValidOption = FALSE;
+ break;
+ }
+ strcpy (jobName, pEqual+1);
+ }
+ else if (IsValidOption (argv[i], __SERVER__, __SHORT_FOR_SERVER__))
+ {
+ if (pEqual == NULL ||
+ *(pEqual+1) == 0 ||
+ strlen (pEqual+1) > MAX_NAME_LEN - 1)
+ {
+ fValidOption = FALSE;
+ break;
+ }
+ pCaptureParams->NDSCapture = FALSE;
+ strcpy (pCaptureParams->serverName, pEqual+1);
+ }
+ else if (IsValidOption (argv[i], __QUEUE__, __SHORT_FOR_QUEUE__))
+ {
+ if (pEqual == NULL ||
+ *(pEqual+1) == 0 ||
+ strlen (pEqual+1) > MAX_QUEUE_NAME_LEN - 1) //compatible.
+ {
+ fValidOption = FALSE;
+ break;
+ }
+ strcpy (pCaptureParams->queueName, pEqual+1);
+ }
+ else if (IsValidOption (argv[i], __PRINTER__, __SHORT_FOR_PRINTER__))
+ {
+ if (pEqual == NULL ||
+ *(pEqual+1) == 0 ||
+ !pCaptureParams->NDSCapture ||
+ strlen (pEqual+1) > MAX_QUEUE_NAME_LEN - 1) //compatible.
+ {
+ fValidOption = FALSE;
+ break;
+ }
+ GetPrinterDefaultQueue( pCaptureParams, pEqual+1 );
+ }
+ else if (IsValidOption (argv[i], __CREATE__, __SHORT_FOR_CREATE__))
+ {
+ if (pEqual != NULL) //compatible.
+ {
+ if (strlen (pEqual+1) > _MAX_PATH - 1)
+ {
+ DisplayMessage(IDR_INVALID_PATH_NAME, pEqual+1);
+ fValidParam = FALSE;
+ break;
+ }
+ strcpy (pCaptureParams->filePath, pEqual+1);
+ }
+ }
+ else if (IsValidOption (argv[i], __FORM__, __SHORT_FOR_FORM__))
+ {
+ int j = 1;
+ int bAllNumbers = TRUE;
+
+ if (pEqual == NULL || *(pEqual+1) == 0)
+ {
+ DisplayMessage(IDR_FORM_EXPECTED);
+ fValidParam = FALSE;
+ break;
+ }
+
+ if (strlen (pEqual+1) > 3) // Only allow 3 digits number.
+ {
+ DisplayMessage(IDR_INVALID_FORM_NAME, pEqual+1);
+ fValidParam = FALSE;
+ break;
+ }
+
+ while (*(pEqual+j) != 0)
+ {
+ if (!isdigit (*(pEqual+j)))
+ {
+ bAllNumbers = FALSE;
+ break;
+ }
+ j++;
+ }
+
+ if (bAllNumbers)
+ {
+ pCaptureParams->captureFlagsRW.FormType = atoi (pEqual+1);
+
+ if (pCaptureParams->captureFlagsRW.FormType > 255)
+ {
+ DisplayMessage(IDR_INVALID_FORM_TYPE);
+ fValidParam = FALSE;
+ break;
+ }
+ }
+ else
+ {
+ DisplayMessage(IDR_INVALID_FORM_NAME, pEqual+1);
+ fValidParam = FALSE;
+ break;
+ }
+ }
+ else if (IsValidOption (argv[i], __COPIES__, __SHORT_FOR_COPIES__))
+ {
+ if (pEqual == NULL || *(pEqual+1) == 0)
+ {
+ DisplayMessage(IDR_COPIES_EXPECTED);
+ fValidParam = FALSE;
+ break;
+ }
+
+ pCaptureParams->captureFlagsRW.NumCopies = atoi (pEqual+1);
+
+ if (pCaptureParams->captureFlagsRW.NumCopies < 1 ||
+ pCaptureParams->captureFlagsRW.NumCopies > 255)
+ {
+ DisplayMessage(IDR_COPIES_OUTOF_RANGE);
+ fValidParam = FALSE;
+ break;
+ }
+ }
+ else if (IsValidOption (argv[i], __TABS__, __SHORT_FOR_TABS__))
+ {
+ if (pEqual == NULL || *(pEqual+1) == 0)
+ {
+ DisplayMessage(IDR_TAB_SIZE_EXPECTED);
+ fValidParam = FALSE;
+ break;
+ }
+
+ pCaptureParams->captureFlagsRW.TabSize = (BYTE) atoi (pEqual+1);
+
+ if (pCaptureParams->captureFlagsRW.TabSize < 1 ||
+ pCaptureParams->captureFlagsRW.TabSize > 18)
+ {
+ DisplayMessage(IDR_TABSIZE_OUTOF_RANGE);
+ fValidParam = FALSE;
+ break;
+ }
+
+ pCaptureParams->captureFlagsRW.PrintFlags |= CAPTURE_FLAG_EXPAND_TABS;
+ }
+ else if (IsValidOption (argv[i], __NAME__, __SHORT_FOR_NAME__))
+ {
+ if (pEqual == NULL ||
+ *(pEqual+1) == 0 ||
+ strlen (pEqual+1) > MAX_BANNER_USER_NAME - 1)
+ {
+ fValidOption = FALSE;
+ break;
+ }
+ strcpy (pCaptureParams->bannerUserName, pEqual+1);
+ }
+ else if (IsValidOption (argv[i], __BANNER__, __SHORT_FOR_BANNER__))
+ {
+ if (pEqual != NULL)
+ {
+ if (strlen (pEqual+1) > MAX_BANNER_USER_NAME - 1)
+ {
+ DisplayMessage(IDR_INVALID_BANNER, pEqual+1);
+ fValidParam = FALSE;
+ break;
+ }
+ strcpy (pCaptureParams->captureFlagsRW.BannerText, pEqual+1);
+ pCaptureParams->captureFlagsRW.PrintFlags |= CAPTURE_FLAG_PRINT_BANNER;
+ }
+ }
+ //
+ // Kludge for LX LPX LPTX parameters
+ // Note that L:X L=X, etc are also valid
+ //
+ else if ( ( pEqual == NULL ) && ( *(argv[i]) == 'L' ) ) {
+ pEqual = argv[i];
+ pEqual++;
+ if ( *pEqual == 'P' ) {
+ pEqual++;
+ if ( *pEqual == 'T' ) {
+ pEqual++;
+ }
+ }
+ pCaptureParams->nLPT = (unsigned char) atoi (pEqual);
+
+ if (pCaptureParams->nLPT < 1 || pCaptureParams->nLPT > 3)
+ {
+ DisplayMessage(IDR_INVALID_LPT_NUMBER);
+ fValidParam = FALSE;
+ break;
+ }
+
+ }
+ else
+ {
+ fValidOption = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (fValidOption && fValidParam)
+ {
+ sprintf (pCaptureParams->captureFlagsRW.JobDescription, __JOB_DESCRIPTION__, pCaptureParams->nLPT);
+ return(TRUE);
+ }
+ else
+ {
+ if (!fValidOption)
+ {
+ if (pEqual)
+ *pEqual = '=';
+ DisplayMessage(IDR_UNKNOW_FLAG, argv[i]);
+ }
+ DisplayMessage(IDR_CAPTURE_USAGE);
+ return(FALSE);
+ }
+}
+
+/*
+ Show the capture setting.
+ */
+void ShowCapture(void)
+{
+ unsigned int iRet = 0;
+ int i;
+ char * queueName;
+
+ for (i = 1; i <= 3; i++ )
+ {
+ NETWARE_CAPTURE_FLAGS_RW captureFlagsRW;
+ NETWARE_CAPTURE_FLAGS_RO captureFlagsRO;
+
+ if (iRet = GetCaptureFlags ((unsigned char)i,
+ &captureFlagsRW,
+ &captureFlagsRO))
+ {
+ DisplayError (iRet, "GetCaptureFlags");
+ }
+ else
+ {
+ char *serverName;
+ WCHAR timeOut[256];
+ WCHAR tabs[256];
+
+ if (captureFlagsRO.LPTCaptureFlag == 0)
+ {
+ DisplayMessage(IDR_NOT_ACTIVE, i);
+ }
+ else
+ {
+ serverName = captureFlagsRO.ServerName;
+
+ if ( !CaptureStringsLoaded ) {
+ (void) LoadString( NULL, IDR_DISABLED, __DISABLED__, 256 );
+ (void) LoadString( NULL, IDR_ENABLED, __ENABLED__, 256 );
+ (void) LoadString( NULL, IDR_YES, __YES__, 256 );
+ (void) LoadString( NULL, IDR_NO, __NO__, 256 );
+ (void) LoadString( NULL, IDR_SECONDS, __SECONDS__, 256 );
+ (void) LoadString( NULL, IDR_CONVERT_TO_SPACE, __CONVERT_TO_SPACE__, 256 );
+ (void) LoadString( NULL, IDR_NO_CONVERSION, __NO_CONVERSION__, 256 );
+ (void) LoadString( NULL, IDR_NOTIFY_USER, __NOTIFY_USER__, 256 );
+ (void) LoadString( NULL, IDR_NOT_NOTIFY_USER, __NOT_NOTIFY_USER__, 256 );
+ (void) LoadString( NULL, IDR_NONE, __NONE__, 256 );
+ }
+
+ if (captureFlagsRW.FlushCaptureTimeout)
+ wsprintf (timeOut, __SECONDS__, captureFlagsRW.FlushCaptureTimeout);
+ else
+ (void) LoadString( NULL, IDR_DISABLED, timeOut, 256 );
+
+ if (captureFlagsRW.PrintFlags & CAPTURE_FLAG_EXPAND_TABS)
+ wsprintf(tabs, __CONVERT_TO_SPACE__, captureFlagsRW.TabSize);
+ else
+ (void) LoadString( NULL, IDR_NO_CONVERSION, tabs, 256 );
+
+
+ queueName = captureFlagsRO.QueueName;
+
+ if ( fNDS )
+ {
+ if ( captureFlagsRW.PrintFlags & CAPTURE_FLAG_PRINT_BANNER )
+ {
+ DisplayMessage(IDR_LPT_STATUS_NDS, i, queueName,
+ captureFlagsRW.PrintFlags & CAPTURE_FLAG_NOTIFY? __NOTIFY_USER__ : __NOT_NOTIFY_USER__, //Notify
+ __DISABLED__, //Capture Defaults
+ captureFlagsRW.FlushCaptureOnClose? __DISABLED__ : __ENABLED__, //AutoEndCap
+ captureFlagsRW.BannerText, //Banner
+ captureFlagsRW.PrintFlags & CAPTURE_FLAG_NO_FORMFEED? __NO__ : __YES__, //Form Feed
+ captureFlagsRW.NumCopies, //Copies
+ tabs, //Tabs
+ captureFlagsRW.FormType, timeOut); //Timeout Counts
+ }
+ else
+ {
+ DisplayMessage(IDR_LPT_STATUS_NO_BANNER_NDS, i, queueName,
+ captureFlagsRW.PrintFlags & CAPTURE_FLAG_NOTIFY? __NOTIFY_USER__ : __NOT_NOTIFY_USER__, //Notify
+ __DISABLED__, //Capture Defaults
+ captureFlagsRW.FlushCaptureOnClose? __DISABLED__ : __ENABLED__, //AutoEndCap
+ __NONE__, //Banner
+ captureFlagsRW.PrintFlags & CAPTURE_FLAG_NO_FORMFEED? __NO__ : __YES__, //Form Feed
+ captureFlagsRW.NumCopies, //Copies
+ tabs, //Tabs
+ captureFlagsRW.FormType, timeOut); //Timeout Counts
+ }
+ }
+ else
+ {
+ if ( captureFlagsRW.PrintFlags & CAPTURE_FLAG_PRINT_BANNER )
+ {
+ DisplayMessage(IDR_LPT_STATUS, i, serverName, queueName,
+ captureFlagsRW.PrintFlags & CAPTURE_FLAG_NOTIFY? __NOTIFY_USER__ : __NOT_NOTIFY_USER__, //Notify
+ __DISABLED__, //Capture Defaults
+ captureFlagsRW.FlushCaptureOnClose? __DISABLED__ : __ENABLED__, //AutoEndCap
+ captureFlagsRW.BannerText, //Banner
+ captureFlagsRW.PrintFlags & CAPTURE_FLAG_NO_FORMFEED? __NO__ : __YES__, //Form Feed
+ captureFlagsRW.NumCopies, //Copies
+ tabs, //Tabs
+ captureFlagsRW.FormType, timeOut); //Timeout Counts
+ }
+ else
+ {
+ DisplayMessage(IDR_LPT_STATUS_NO_BANNER, i, serverName, queueName,
+ captureFlagsRW.PrintFlags & CAPTURE_FLAG_NOTIFY? __NOTIFY_USER__ : __NOT_NOTIFY_USER__, //Notify
+ __DISABLED__, //Capture Defaults
+ captureFlagsRW.FlushCaptureOnClose? __DISABLED__ : __ENABLED__, //AutoEndCap
+ __NONE__, //Banner
+ captureFlagsRW.PrintFlags & CAPTURE_FLAG_NO_FORMFEED? __NO__ : __YES__, //Form Feed
+ captureFlagsRW.NumCopies, //Copies
+ tabs, //Tabs
+ captureFlagsRW.FormType, timeOut); //Timeout Counts
+ }
+ }
+ }
+ }
+ }
+}
+
+int CStartCapture(unsigned int conn,
+ PCAPTURE_PARAMS pCaptureParams)
+{
+ unsigned int iRet = 0;
+ unsigned char FullPath[255 + NCP_VOLUME_LENGTH];
+ unsigned char DirPath[255];
+ unsigned char VolumeName[NCP_VOLUME_LENGTH];
+ WORD status;
+
+ // Get connection handle.
+ if ( !pCaptureParams->NDSCapture )
+ {
+ if ( pCaptureParams->serverName[0] == 0 )
+ {
+ if (iRet = GetFileServerName (conn, pCaptureParams->serverName))
+ {
+ DisplayError (iRet, "GetFileServerName");
+ return (1);
+ }
+ }
+ else
+ {
+ if (iRet = GetConnectionHandle (pCaptureParams->serverName, &conn))
+ {
+ if ( iRet = NTLoginToFileServer( pCaptureParams->serverName, "GUEST", "" ) ) {
+ switch ( iRet ) {
+ case ERROR_INVALID_PASSWORD:
+ case ERROR_NO_SUCH_USER:
+ case ERROR_CONNECTION_COUNT_LIMIT:
+ case ERROR_LOGIN_TIME_RESTRICTION:
+ case ERROR_LOGIN_WKSTA_RESTRICTION:
+ case ERROR_ACCOUNT_DISABLED:
+ case ERROR_PASSWORD_EXPIRED:
+ case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED:
+ DisplayMessage( IDR_CAPTURE_FAILED, pCaptureParams->queueName );
+ DisplayMessage( IDR_ACCESS_DENIED );
+ break;
+ default:
+ DisplayMessage(IDR_SERVER_NOT_FOUND, pCaptureParams->serverName);
+ }
+ return (1);
+ }
+ else {
+ if (iRet = GetConnectionHandle (pCaptureParams->serverName, &conn)) {
+ DisplayMessage(IDR_SERVER_NOT_FOUND, pCaptureParams->serverName);
+ return (1);
+ }
+ }
+ }
+ }
+ }
+
+ if (pCaptureParams->filePath[0] != 0)
+ {
+ DisplayMessage(IDR_FILE_CAPTURE_UNSUPPORTED);
+ return (1);
+ }
+ else
+ {
+ if (pCaptureParams->queueName[0] == 0)
+ {
+ if ( pCaptureParams->NDSCapture )
+ {
+ DisplayMessage(IDR_NO_QUEUE);
+ return (1);
+ }
+ else
+ {
+ // Try to get the default queue ID and name.
+ if (iRet = GetDefaultPrinterQueue (conn, pCaptureParams->serverName, pCaptureParams->queueName))
+ {
+ DisplayMessage(IDR_NO_PRINTERS, pCaptureParams->serverName);
+ return (1);
+ }
+ }
+ }
+ // Start queue capture.
+ if ( pCaptureParams->NDSCapture )
+ {
+ char szCanonName[MAX_QUEUE_NAME_LEN];
+
+ // Get the full name of the printer queue
+ // The redirectory wants root based names for
+ // everything.
+
+ iRet = NDSCanonicalizeName( pCaptureParams->queueName,
+ szCanonName,
+ NDS_NAME_CHARS,
+ TRUE );
+
+ if ( iRet && ( pCaptureParams->queueName[0] != '.' ) )
+ {
+ // If that didn't work, see if it's a root
+ // based name without the leading period.
+
+ strcpy( szCanonName, "." );
+ strcat( szCanonName, pCaptureParams->queueName );
+
+ iRet = NDSCanonicalizeName( szCanonName,
+ szCanonName,
+ MAX_QUEUE_NAME_LEN,
+ TRUE );
+ }
+
+ if ( iRet )
+ iRet = ERROR_BAD_NETPATH;
+ else
+ iRet = StartQueueCapture ( conn,
+ pCaptureParams->nLPT,
+ NDSTREE,
+ szCanonName );
+ }
+ else
+ {
+ iRet = StartQueueCapture (conn,
+ pCaptureParams->nLPT,
+ pCaptureParams->serverName,
+ pCaptureParams->queueName);
+ }
+
+ if ( iRet )
+ {
+ switch ( iRet ) {
+ case ERROR_ACCESS_DENIED:
+ case ERROR_INVALID_PASSWORD:
+ DisplayMessage (IDR_CAPTURE_FAILED, pCaptureParams->queueName);
+ DisplayMessage (IDR_ACCESS_DENIED);
+ break;
+ case ERROR_EXTENDED_ERROR:
+ NTPrintExtendedError();
+ break;
+ case ERROR_BAD_NET_NAME:
+ case ERROR_BAD_NETPATH:
+ if ( pCaptureParams->NDSCapture )
+ DisplayMessage (IDR_NDSQUEUE_NOT_EXIST,
+ pCaptureParams->queueName,
+ pCaptureParams->serverName );
+ else
+ DisplayMessage (IDR_QUEUE_NOT_EXIST,
+ pCaptureParams->queueName,
+ pCaptureParams->serverName );
+ break;
+ default:
+ DisplayError (iRet, "StartQueueCapture");
+ break;
+ }
+ return (1);
+ }
+ }
+
+ if (pCaptureParams->captureFlagsRW.FlushCaptureOnClose == 1)
+ DisplayMessage(IDR_NO_AUTOENDCAP);
+
+ if ( pCaptureParams->NDSCapture )
+ DisplayMessage(IDR_NDSSUCCESS_QUEUE, pCaptureParams->nLPT,
+ pCaptureParams->queueName);
+ else
+ DisplayMessage(IDR_SUCCESS_QUEUE, pCaptureParams->nLPT,
+ pCaptureParams->queueName, pCaptureParams->serverName);
+
+ return(0);
+}
+
+/*
+ * Given an NDS printer name, fill in the default queue name
+ *
+ */
+int
+GetPrinterDefaultQueue( PCAPTURE_PARAMS pCaptureParams,
+ PBYTE PrinterName )
+{
+ BYTE Fixup[ MAX_QUEUE_NAME_LEN];
+ PBYTE ptr;
+ unsigned int iRet;
+
+ iRet = NDSGetProperty ( PrinterName, "Default Queue",
+ pCaptureParams->queueName,
+ MAX_QUEUE_NAME_LEN,
+ NULL );
+ if ( iRet )
+ {
+ /*
+ * Strip off the . in front and add context at end
+ */
+ ptr = RemoveSpaces (PrinterName);
+ if ( *ptr == '.' )
+ {
+ ptr++;
+ strncpy( Fixup, ptr, MAX_QUEUE_NAME_LEN );
+ }
+ else
+ {
+ strncpy( Fixup, ptr, MAX_QUEUE_NAME_LEN );
+ if ( Fixup[strlen(Fixup)-1] != '.' )
+ {
+ strcat( Fixup, "." );
+ }
+ (void) NDSGetContext( Fixup + strlen(Fixup),
+ MAX_QUEUE_NAME_LEN - strlen(Fixup) );
+ }
+ iRet = NDSGetProperty ( Fixup, "Default Queue",
+ pCaptureParams->queueName,
+ MAX_QUEUE_NAME_LEN,
+ NULL );
+ if ( !iRet )
+ ConvertUnicodeToAscii( pCaptureParams->queueName );
+ }
+
+ return iRet;
+}
diff --git a/private/nw/nwscript/common.c b/private/nw/nwscript/common.c
new file mode 100644
index 000000000..019ff87e5
--- /dev/null
+++ b/private/nw/nwscript/common.c
@@ -0,0 +1,400 @@
+
+/*************************************************************************
+*
+* COMMON.C
+*
+* Miscellaneous routines for scripts, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\COMMON.C $
+*
+* Rev 1.3 10 Apr 1996 14:21:52 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.3 12 Mar 1996 19:52:40 terryt
+* Relative NDS names and merge
+*
+* Rev 1.2 24 Jan 1996 17:14:54 terryt
+* Common read string routine
+*
+* Rev 1.1 22 Dec 1995 14:23:56 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:36 terryt
+* Initial revision.
+*
+* Rev 1.2 25 Aug 1995 16:22:18 terryt
+* Capture support
+*
+* Rev 1.1 26 Jul 1995 14:17:06 terryt
+* Clean up comments
+*
+* Rev 1.0 15 May 1995 19:10:18 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include "common.h"
+
+/*
+ Used by DisplayMapping() only.
+ Return search number if the drive is a search drive.
+ Return 0 if the drive is not a search drive.
+ */
+int IsSearchDrive(int driveNum)
+{
+ int searchNum = 1;
+ char *path;
+
+ path = NWGetPath();
+
+ while (*path != 0)
+ {
+ if ((*path - 'A' + 1 == driveNum) &&
+ (*(path+1) == ':'))
+ {
+ return searchNum;
+ }
+
+ if (path = strchr (path, ';'))
+ {
+ path++;
+ searchNum++;
+ }
+ else
+ return(0);
+ }
+
+ return(0);
+}
+
+
+/*
+ Get path enviroment variable. This returns the pointer to the
+ path in the parent enviroment segment.
+ */
+char * NWGetPath(void)
+{
+ //
+ // On NT we can't change or get the parent's environment this way
+ //
+ return( getenv("PATH") );
+}
+
+/*
+ Return TRUE if the memory block is large enough for adding new
+ search path. FALSE otherwise.
+ */
+int MemorySegmentLargeEnough (int nInsertByte)
+{
+ return TRUE;
+}
+
+/*
+ Display drive maps info.
+ */
+void DisplayMapping(void)
+{
+ unsigned int iRet = 0;
+ int i;
+ WORD status;
+ char rootPath[MAX_PATH_LEN], relativePath[MAX_PATH_LEN];
+ char *envPath, *tokenPath;
+ char *path;
+ DWORD LocalDrives;
+ DWORD NonSearchDrives;
+ char sLocalDrives[26*2+5];
+ char * sptr;
+
+ // Don't delete this line. This is for fixing bug 1176.
+ DisplayMessage(IDR_NEWLINE);
+
+ LocalDrives = 0;
+ NonSearchDrives = 0;
+
+ // Collect local drives and search drives
+ for (i = 1; i <= 26; i++) {
+ status = NTNetWareDriveStatus( (unsigned short)(i-1) );
+ if ((status & NETWARE_LOCAL_DRIVE) && !(status & NETWARE_NETWORK_DRIVE))
+ LocalDrives |= ( 1 << (i-1) );
+ else if ((status & NETWARE_NETWORK_DRIVE) && (!IsSearchDrive(i)) )
+ {
+ if (status & NETWARE_NETWARE_DRIVE)
+ NonSearchDrives |= ( 1 << (i-1) );
+ else
+ {
+ //For NetWare compatibility
+ LocalDrives |= ( 1 << (i-1) );
+ }
+ }
+ }
+
+ // Print out local drives
+ if ( LocalDrives ) {
+ sptr = &sLocalDrives[0];
+ for (i = 1; i <= 26; i++)
+ {
+ if ( LocalDrives & ( 1 << (i - 1) ) ) {
+ *sptr++ = 'A' + i - 1;
+ *sptr++ = ',';
+ }
+ }
+ sptr--;
+ *sptr = '\0';
+ DisplayMessage(IDR_ALL_LOCAL_DRIVES, sLocalDrives);
+ }
+
+ // Print out non search drives.
+ for (i = 1; i <= 26; i++)
+ {
+ if ( NonSearchDrives & ( 1 << (i - 1) ) ) {
+
+ if (iRet = GetDriveStatus ((unsigned short)i,
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ rootPath,
+ relativePath,
+ NULL))
+ {
+ DisplayError (iRet, "GetDriveStatus");
+ }
+ else
+ {
+ DisplayMessage(IDR_NETWARE_DRIVE, 'A'+i-1, rootPath, relativePath);
+ }
+ }
+ }
+
+ // Print out dashed line as seperator between non search drives
+ // and search drives.
+ DisplayMessage(IDR_DASHED_LINE);
+
+ // Get the PATH environment variable.
+ path = NWGetPath();
+ if ((envPath = malloc (strlen (path) + 1)) == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+
+ strcpy (envPath, path);
+
+ tokenPath = strtok (envPath, PATH_SEPERATOR);
+
+ // Print out search drvies.
+ for (i = 1; tokenPath != NULL; i++)
+ {
+ if (tokenPath[1] == ':')
+ {
+ if (iRet = GetDriveStatus ((unsigned short)(toupper(tokenPath[0])-'A'+1),
+ NETWARE_FORMAT_SERVER_VOLUME,
+ &status,
+ NULL,
+ rootPath,
+ relativePath,
+ NULL))
+ {
+ DisplayError (iRet, "GetDriveStatus");
+ }
+ else
+ {
+ if (status & NETWARE_NETWARE_DRIVE)
+ DisplayMessage(IDR_NETWARE_SEARCH, i, tokenPath, rootPath, relativePath);
+ else
+ DisplayMessage(IDR_LOCAL_SEARCH, i, tokenPath);
+ }
+ }
+ else
+ {
+ // Path is specified without drive letter.
+ DisplayMessage(IDR_LOCAL_SEARCH, i, tokenPath);
+ }
+
+ tokenPath = strtok (NULL, PATH_SEPERATOR);
+ }
+
+ free (envPath);
+}
+
+/*****************************************************************************
+ * *
+ * GetString *
+ * *
+ * *
+ * entry: pointer to buffer *
+ * length of buffer *
+ * *
+ * exit: length of string *
+ * *
+ *****************************************************************************/
+
+int
+GetString( char * pBuffer, int ByteCount )
+{
+ char * pString = pBuffer;
+ char ch;
+
+ if ( ByteCount > 0 )
+ ByteCount--;
+
+ for( ;; ) {
+
+ switch ( ch = (char) _getch() ) {
+
+ case '\r' :
+ *pString++ = '\0';
+ putchar( '\n' );
+ return( strlen( pBuffer ) );
+
+ case '\b' :
+ if ( pString != pBuffer ) {
+ ByteCount++;
+ pString--;
+ printf( "\b \b" );
+ }
+ break;
+
+ default :
+ if ( ByteCount > 0 && ch >= 0x20 && ch < 0x80 ) {
+ *pString++ = ch;
+ ByteCount--;
+ putchar( ch );
+ }
+ break;
+ }
+
+ }
+ fflush(stdin);
+}
+
+/*
+ Read user or server name from the keyboard input.
+ Return TRUE if user typed in a username
+ FALSE otherwise.
+ */
+int ReadName (char * Name)
+{
+ memset( Name, 0, MAX_NAME_LEN );
+
+ if ( 0 == GetString( Name, MAX_NAME_LEN ) )
+ return FALSE;
+
+ _strupr(Name);
+ return TRUE;
+}
+
+
+
+/*
+ Try to log the user in.
+ Return error code. 0 is success.
+ */
+int Login( char *UserName,
+ char *ServerName,
+ char *Password,
+ int bReadPassword)
+{
+ unsigned int iRet = 0;
+
+ // Try log the user in with no password first.
+ iRet = NTLoginToFileServer( ServerName,
+ UserName,
+ Password);
+
+ if (iRet == ERROR_INVALID_PASSWORD && bReadPassword)
+ {
+ // wrong password. ask for passowrd. and try login with
+ // the input password.
+ DisplayMessage(IDR_PASSWORD, UserName, ServerName);
+
+ ReadPassword (Password);
+
+ iRet = NTLoginToFileServer( ServerName,
+ UserName,
+ Password);
+ }
+
+ switch(iRet)
+ {
+ case NO_ERROR: // ok
+ DisplayMessage(IDR_ATTACHED, ServerName);
+ break;
+
+ case ERROR_INVALID_PASSWORD: // wrong password.
+ case ERROR_NO_SUCH_USER: // no such user.
+ DisplayMessage(IDR_SERVER_USER, ServerName, UserName);
+ DisplayMessage(IDR_ACCESS_DENIED);
+ break;
+
+ case ERROR_CONNECTION_COUNT_LIMIT: // concurrent connection restriction.
+ DisplayMessage(IDR_SERVER_USER, ServerName, UserName);
+ DisplayMessage(IDR_LOGIN_DENIED_NO_CONNECTION);
+ break;
+
+ case ERROR_LOGIN_TIME_RESTRICTION: // time restriction.
+ DisplayMessage(IDR_SERVER_USER, ServerName, UserName);
+ DisplayMessage(IDR_UNAUTHORIZED_LOGIN_TIME);
+ break;
+
+ case ERROR_LOGIN_WKSTA_RESTRICTION: // station restriction.
+ DisplayMessage(IDR_SERVER_USER, ServerName, UserName);
+ DisplayMessage(IDR_UNAUTHORIZED_LOGIN_STATION);
+ break;
+
+ case ERROR_ACCOUNT_DISABLED:
+ DisplayMessage(IDR_SERVER_USER, ServerName, UserName);
+ DisplayMessage(IDR_ACCOUNT_DISABLED);
+ break;
+
+ case ERROR_PASSWORD_EXPIRED: // password expired and no grace login left.
+ DisplayMessage(IDR_SERVER_USER, ServerName, UserName);
+ DisplayMessage(IDR_PASSWORD_EXPRIED_NO_GRACE);
+ break;
+
+ case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED:
+ // Server rejected access
+ DisplayMessage(IDR_CONNECTION_REFUSED);
+ break;
+
+ case ERROR_EXTENDED_ERROR:
+ NTPrintExtendedError();
+ break;
+
+ default :
+ DisplayError(iRet,"LoginToFileServer");
+ break;
+ }
+
+ return(iRet);
+}
+
+int CAttachToFileServer(char *ServerName, unsigned int *pConn, int * pbAlreadyAttached)
+{
+ unsigned int iRet = 0;
+
+ if (pbAlreadyAttached != NULL)
+ *pbAlreadyAttached = FALSE;
+
+ // Validate the server name.
+ iRet = AttachToFileServer(ServerName,pConn);
+
+ switch (iRet)
+ {
+ case 0: // OK
+ break;
+
+ case 0x8800 : // Already atached.
+ if (pbAlreadyAttached != NULL)
+ *pbAlreadyAttached = TRUE;
+
+ iRet = GetConnectionHandle (ServerName, pConn);
+ break;
+
+ default:
+ DisplayMessage(IDR_NO_RESPONSE, ServerName);
+ break;
+ }
+
+ return(iRet);
+}
diff --git a/private/nw/nwscript/date.c b/private/nw/nwscript/date.c
new file mode 100644
index 000000000..1533d1f19
--- /dev/null
+++ b/private/nw/nwscript/date.c
@@ -0,0 +1,78 @@
+/*************************************************************************
+*
+* DATE.C
+*
+* NT date routine
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\DATE.C $
+*
+* Rev 1.2 10 Apr 1996 14:22:00 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:52:56 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:24:04 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:40 terryt
+* Initial revision.
+*
+* Rev 1.0 15 May 1995 19:10:22 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "nwscript.h"
+
+
+/*
+ *******************************************************************
+
+ NTGetTheDate
+
+Routine Description:
+
+ Return the current date
+
+Arguments:
+
+ yearCurrent pointer to current year
+ 1980-2099
+ monthCurrent pointer to current month
+ 1-12
+ dayCurrent pointer to current day
+ 1-31
+
+Return Value:
+
+
+
+ *******************************************************************
+ */
+void NTGetTheDate( unsigned int * yearCurrent,
+ unsigned char * monthCurrent,
+ unsigned char * dayCurrent )
+{
+ time_t timedat;
+ struct tm * p_tm;
+
+ (void) time( &timedat );
+ p_tm = localtime( &timedat );
+
+ *yearCurrent = p_tm->tm_year + 1900;
+ *monthCurrent = p_tm->tm_mon + 1;
+ *dayCurrent = p_tm->tm_mday;
+}
diff --git a/private/nw/nwscript/dbcs.c b/private/nw/nwscript/dbcs.c
new file mode 100644
index 000000000..f37beacb6
--- /dev/null
+++ b/private/nw/nwscript/dbcs.c
@@ -0,0 +1,98 @@
+
+/*************************************************************************
+*
+* DBCS.C
+*
+* DBCS routines, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\DBCS.C $
+*
+* Rev 1.1 22 Dec 1995 14:24:10 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:44 terryt
+* Initial revision.
+*
+* Rev 1.1 25 Aug 1995 16:22:26 terryt
+* Capture support
+*
+* Rev 1.0 15 May 1995 19:10:24 terryt
+* Initial revision.
+*
+*************************************************************************/
+/*
+** dbcs.c - DBCS functions for DOS apps.
+**
+** Written by RokaH and DavidDi.
+*/
+
+
+/* Headers
+**********/
+
+// IsDBCSLeadByte taken out of NT because there is one built in.
+// I left the Next and Prev in because I don't know whether this
+// algorithm is "safer" than the built in code.
+
+#include "common.h"
+
+/*
+** unsigned char *NWAnsiNext(unsigned char *puch);
+**
+** Moves to the next character in a string.
+**
+** Arguments: puch - pointer to current location in string
+**
+** Returns: char * - Pointer to next character in string.
+**
+** Globals: none
+**
+** N.b., if puch points to a null character, NWAnsiNext() will return puch.
+*/
+unsigned char *NWAnsiNext(unsigned char *puch)
+{
+ if (*puch == '\0')
+ return(puch);
+ else if (IsDBCSLeadByte(*puch))
+ puch++;
+
+ puch++;
+
+ return(puch);
+}
+
+
+/*
+** unsigned char *NWAnsiPrev(unsigned char *psz, unsigned char *puch);
+**
+** Moves back one character in a string.
+**
+** Arguments: psz - pointer to start of string
+** puch - pointer to current location in string
+**
+** Returns: char * - Pointer to previous character in string.
+**
+** Globals: none
+**
+** N.b., if puch <= psz, NWAnsiPrev() will return psz.
+**
+** This function is implemented in a very slow fashion because we do not wish
+** to trust that the given string is necessarily DBCS "safe," i.e., contains
+** only single-byte characters and valid DBCS characters. So we start from
+** the beginning of the string and work our way forward.
+*/
+unsigned char *NWAnsiPrev(unsigned char *psz, unsigned char *puch)
+{
+ unsigned char *puchPrevious;
+
+ do
+ {
+ puchPrevious = psz;
+ psz = NWAnsiNext(psz);
+ } while (*psz != '\0' && psz < puch);
+
+ return(puchPrevious);
+}
+
diff --git a/private/nw/nwscript/display.c b/private/nw/nwscript/display.c
new file mode 100644
index 000000000..ddd44e3d7
--- /dev/null
+++ b/private/nw/nwscript/display.c
@@ -0,0 +1,101 @@
+
+/*************************************************************************
+*
+* DISPLAY.C
+*
+* NetWare script routines for displaying information, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\DISPLAY.C $
+*
+* Rev 1.2 10 Apr 1996 14:22:06 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:53:04 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:24:18 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:48 terryt
+* Initial revision.
+*
+* Rev 1.1 25 Aug 1995 16:22:32 terryt
+* Capture support
+*
+* Rev 1.0 15 May 1995 19:10:26 terryt
+* Initial revision.
+*
+*************************************************************************/
+/*
+ File name: display.c
+ Do not add any other functions to this file.
+ Otherwise many exes size will increase.
+ */
+
+
+#include "common.h"
+
+/*
+ Display error report.
+ */
+void DisplayError(int error ,char *functionName)
+{
+ DisplayMessage(IDR_ERROR, error ,functionName);
+}
+
+void xstrupr(char *buffer)
+{
+ for (; *buffer; buffer++)
+ {
+ if (IsDBCSLeadByte(*buffer))
+ buffer++;
+ else if (*buffer == 0xff80)
+ *buffer = (char)0xff87;
+ else if (*buffer == 0xff81)
+ *buffer = (char)0xff9a;
+ else if (*buffer == 0xff82)
+ *buffer = (char)0xff90;
+ else if (*buffer == 0xff84)
+ *buffer = (char)0xff8e;
+ else if (*buffer == 0xff88)
+ *buffer = (char)0xff9f;
+ else if (*buffer == 0xff91)
+ *buffer = (char)0xff92;
+ else if (*buffer == 0xff94)
+ *buffer = (char)0xff99;
+ else if (*buffer == 0xffa4)
+ *buffer = (char)0xffa5;
+ }
+
+ _strupr (buffer);
+}
+
+/*
+ Read password from the keyboard input.
+ */
+void ReadPassword(char * Password)
+{
+ int i = 0;
+ char c;
+
+ do
+ { c=(char)_getch();
+
+ if (c == '\b')
+ {
+ if (i > 0)
+ i--;
+ }
+ else
+ {
+ Password[i]=c;
+ i++;
+ }
+ }while((c!='\r') && i< MAX_PASSWORD_LEN );
+ Password[i-1]='\0';
+ xstrupr(Password);
+ DisplayMessage(IDR_NEWLINE);
+}
+
diff --git a/private/nw/nwscript/drive.c b/private/nw/nwscript/drive.c
new file mode 100644
index 000000000..b6539185d
--- /dev/null
+++ b/private/nw/nwscript/drive.c
@@ -0,0 +1,327 @@
+/*************************************************************************
+*
+* DRIVE.C
+*
+* NT drive routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\DRIVE.C $
+*
+* Rev 1.2 10 Apr 1996 14:22:12 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:53:22 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:24:24 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:52 terryt
+* Initial revision.
+*
+* Rev 1.2 25 Aug 1995 16:22:38 terryt
+* Capture support
+*
+* Rev 1.1 23 May 1995 19:36:46 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:10:30 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <nwapi32.h>
+#include <nwapi.h>
+#include <npapi.h>
+
+#include "nwscript.h"
+#include "ntnw.h"
+#include "inc/nwlibs.h"
+
+#include "..\..\..\inc\mpr.h"
+
+extern unsigned char NW_PROVIDERA[];
+
+/********************************************************************
+
+ GetFirstDrive
+
+Routine Description:
+
+ Return the first non-local drive
+
+Arguments:
+
+ pFirstDrive = pointer to drive
+ 1-26
+
+Return Value:
+ 0 = success
+ F = failure
+
+ ********************************************************************/
+unsigned int
+GetFirstDrive( unsigned short *pFirstDrive )
+{
+ int i;
+ char DriveName[10];
+ unsigned int drivetype;
+
+ strcpy( DriveName, "A:\\" );
+
+ for ( i = 2; i < 26; i++ ) {
+ DriveName[0] = 'A' + i;
+ drivetype = GetDriveTypeA( DriveName );
+ if ( ( ( drivetype == DRIVE_REMOTE ) &&
+ ( NTIsNetWareDrive( i ) ) ) ||
+ ( drivetype == DRIVE_NO_ROOT_DIR ) ) {
+ *pFirstDrive = i + 1;
+ return 0x0000;
+ }
+ }
+
+ return 0x000F;
+}
+
+/********************************************************************
+
+ IsDriveRemote
+
+Routine Description:
+
+ Is the given drive remote?
+
+Arguments:
+
+ DriveNumber 1-26
+ pRemote 0x1000 = remote, 0x0000 = local
+
+Return Value:
+ 0 = success
+ F = invalid drive
+
+ ********************************************************************/
+unsigned int
+IsDriveRemote(
+ unsigned char DriveNumber,
+ unsigned int *pRemote
+ )
+{
+ char DriveName[10];
+ unsigned int drivetype;
+
+ strcpy( DriveName, "A:\\" );
+ DriveName[0] = 'A' + DriveNumber;
+
+ drivetype = GetDriveTypeA( DriveName );
+
+ if ( drivetype == DRIVE_REMOTE ) {
+ *pRemote = 0x1000;
+ return 0;
+ }
+ else if ( drivetype == DRIVE_NO_ROOT_DIR ) {
+ return 0xF;
+ }
+ else {
+ *pRemote = 0;
+ return 0;
+ }
+}
+
+
+/********************************************************************
+
+ NTNetWareDriveStatus
+
+Routine Description:
+
+ Return the type of drive
+
+Arguments:
+
+ DriveNumber - Number of drive 0-25
+
+Return Value:
+
+ Combination of:
+ NETWARE_NETWORK_DRIVE
+ NETWARE_NETWARE_DRIVE
+ NETWARE_LOCAL_FREE_DRIVE
+ NETWARE_LOCAL_DRIVE
+
+
+
+ *******************************************************************/
+unsigned short
+NTNetWareDriveStatus( unsigned short DriveNumber )
+{
+ char DriveName[10];
+ unsigned int drivetype;
+ unsigned int Status = 0;
+
+ strcpy( DriveName, "A:\\" );
+ DriveName[0] = 'A' + DriveNumber;
+ drivetype = GetDriveTypeA( DriveName );
+
+ if ( drivetype == DRIVE_REMOTE ) {
+ Status |= NETWARE_NETWORK_DRIVE;
+ if ( NTIsNetWareDrive( (unsigned int)DriveNumber ) )
+ Status |= NETWARE_NETWARE_DRIVE;
+ }
+ else if ( drivetype == DRIVE_NO_ROOT_DIR ) {
+ Status = NETWARE_LOCAL_FREE_DRIVE;
+ }
+ else {
+ Status = NETWARE_LOCAL_DRIVE;
+ }
+ return Status;
+}
+
+
+/********************************************************************
+
+ NTGetNWDrivePath
+
+Routine Description:
+
+ Return the server name and path of the specified drive
+
+Arguments:
+ DriveNumber - Number of drive 0-25
+ ServerName - Name of file server
+ Path - Volume:\Path
+
+Return Value:
+ 0 = success
+ else NT error
+
+ *******************************************************************/
+unsigned int NTGetNWDrivePath(
+ unsigned short DriveNumber,
+ unsigned char * ServerName,
+ unsigned char * Path )
+{
+ static char localname[] = "A:";
+ unsigned int Result;
+ char * p;
+ char * volume;
+ char remotename[1024];
+ int length = 1024;
+
+ if ( ServerName != NULL )
+ *ServerName = 0;
+
+ if ( Path != NULL );
+ *Path = 0;
+
+ localname[0] = 'A' + DriveNumber;
+
+ Result = WNetGetConnectionA ( localname, remotename, &length );
+
+ if ( Result != NO_ERROR ) {
+ Result = GetLastError();
+ if ( Result == ERROR_EXTENDED_ERROR )
+ NTPrintExtendedError();
+ return Result;
+ }
+
+ p = strchr (remotename + 2, '\\');
+ if ( !p )
+ return 0xffffffff;
+
+ *p++ = '\0';
+ volume = p;
+
+ if ( ServerName != NULL ) {
+ strcpy( ServerName, remotename + 2 );
+ _strupr( ServerName );
+ }
+
+ if ( Path != NULL ) {
+ p = strchr (volume, '\\');
+ if ( !p ) {
+ strcpy( Path, volume );
+ strcat( Path, ":" );
+ }
+ else {
+ *p = ':';
+ strcpy( Path, volume );
+ }
+ _strupr( Path );
+ }
+
+ return NO_ERROR;
+}
+
+
+/********************************************************************
+
+ NTIsNetWareDrive
+
+Routine Description:
+
+ Returns TRUE if the drive is a netware mapped drive
+
+Arguments:
+
+ DriveNumber - Number of drive 0-25
+
+Return Value:
+ TRUE - drive is NetWare
+ FALSE - drive is not NetWare
+
+ *******************************************************************/
+unsigned int
+NTIsNetWareDrive( unsigned int DriveNumber )
+{
+ LPBYTE Buffer ;
+ DWORD dwErr ;
+ HANDLE EnumHandle ;
+ char DriveName[10];
+ DWORD BufferSize = 4096;
+ LPWNET_CONNECTIONINFOA pConnectionInfo;
+
+ strcpy( DriveName, "A:" );
+
+ DriveName[0] = 'A' + DriveNumber;
+
+ //
+ // allocate memory and open the enumeration
+ //
+ if (!(Buffer = LocalAlloc( LPTR, BufferSize ))) {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ dwErr = WNetGetConnection2A( DriveName, Buffer, &BufferSize );
+ if (dwErr != WN_SUCCESS) {
+ dwErr = GetLastError();
+ if ( dwErr == ERROR_EXTENDED_ERROR )
+ NTPrintExtendedError();
+ (void) LocalFree((HLOCAL) Buffer) ;
+ return FALSE;
+ }
+
+ pConnectionInfo = (LPWNET_CONNECTIONINFOA) Buffer;
+
+ if ( !_strcmpi ( pConnectionInfo->lpProvider, NW_PROVIDERA ) ) {
+ (void) LocalFree((HLOCAL) Buffer) ;
+ return TRUE;
+ }
+ else {
+ (void) LocalFree((HLOCAL) Buffer) ;
+ return FALSE;
+ }
+
+ return FALSE;
+}
diff --git a/private/nw/nwscript/drvstat.c b/private/nw/nwscript/drvstat.c
new file mode 100644
index 000000000..908359d79
--- /dev/null
+++ b/private/nw/nwscript/drvstat.c
@@ -0,0 +1,268 @@
+
+/*************************************************************************
+*
+* DRVSTAT.C
+*
+* Drive status routines, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\DRVSTAT.C $
+*
+* Rev 1.2 10 Apr 1996 14:22:20 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:53:36 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:24:32 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:54 terryt
+* Initial revision.
+*
+* Rev 1.1 25 Aug 1995 16:22:44 terryt
+* Capture support
+*
+* Rev 1.0 15 May 1995 19:10:32 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+/*++
+
+Copyright (c) 1994 Micro Computer Systems, Inc.
+
+Module Name:
+
+ nwlibs\drvstat.c
+
+Abstract:
+
+ Directory APIs.
+
+Author:
+
+ Shawn Walker (v-swalk) 10-10-1994
+
+Revision History:
+
+--*/
+#include "common.h"
+
+
+/*++
+*******************************************************************
+
+ GetDriveStatus
+
+Routine Description:
+
+ Get the drive status.
+
+Arguments:
+
+ DriveNumber = The drive to number to use. (1=A,2=B,C=3,...)
+ PathFormat = Format for the return path.
+ NW_FORMAT_NETWARE - volume:path
+ NW_FORMAT_SERVER_VOLUME - server\volume:path
+ NW_FORMAT_DRIVE - G:\path
+ NW_FORMAT_UNC - \\server\volume\path
+ pStatus = A pointer to return the status of the drive.
+ pConnectionHandle = A pointer to return the connection handle
+ for the drive.
+ pRootPath = The pointer to return the base root path. OPTIONAL
+ pRelativePath = The pointer to return the relative to root path.
+ pFullPath = The pointer to return the full path.
+
+Return Value:
+
+ 0x0000 SUCCESSFUL
+ 0x00FF INVALID_DRIVE
+
+*******************************************************************
+--*/
+unsigned int
+GetDriveStatus(
+ unsigned short DriveNumber,
+ unsigned short PathFormat,
+ unsigned short *pStatus,
+ unsigned int *pConnectionHandle,
+ unsigned char *pRootPath,
+ unsigned char *pRelativePath,
+ unsigned char *pFullPath
+ )
+{
+ unsigned char *p;
+ unsigned int Result;
+ unsigned short Status;
+ unsigned char Path[NCP_MAX_PATH_LENGTH + 1];
+ unsigned char WorkPath[NCP_MAX_PATH_LENGTH + 1];
+ unsigned char ServerName[NCP_SERVER_NAME_LENGTH + 1];
+
+ /** Make sure the drive number is valid **/
+
+ if (DriveNumber < 1 || DriveNumber > 32) {
+ return 0x000F; /* INVALID_DRIVE */
+ }
+
+ Status = 0;
+
+ DriveNumber--;
+
+
+ if (pConnectionHandle) {
+ /*
+ * This should never occur.
+ */
+ DisplayError (0xff, "GetDriveStatus");
+ return 0xff;
+ }
+
+ /** Get the directory path from the server **/
+ Result = NTGetNWDrivePath( DriveNumber, ServerName, Path );
+ if ( Result ) {
+ *Path = 0;
+ *ServerName = 0;
+ }
+
+ /** Convert the / in the path to \ **/
+ for (p = Path; *p != 0 ; p++)
+ {
+ if (*p == '/')
+ *p = '\\';
+ }
+
+ /** Get the status of the drive if we need to **/
+ Status = NTNetWareDriveStatus( DriveNumber );
+
+ /** Get the status of the drive if we need to **/
+
+ if (pStatus) {
+ *pStatus = Status;
+ }
+
+ /** Get the full path if we need to **/
+
+ if (pFullPath) {
+
+ if (Status & NETWARE_LOCAL_FREE_DRIVE) {
+ *pFullPath = 0;
+ }
+ else {
+ strcpy(WorkPath, Path);
+
+ /** Build the NetWare path format (volume:path) **/
+
+ if (PathFormat == NETWARE_FORMAT_NETWARE) {
+ strcpy(pFullPath, WorkPath);
+ }
+
+ /** Build the server volume path (server\volume:path) **/
+
+ else if (PathFormat == NETWARE_FORMAT_SERVER_VOLUME) {
+ sprintf(pFullPath, "%s\\%s", ServerName, WorkPath);
+ }
+
+ /** Build the drive path (G:\path) **/
+
+ else if (PathFormat == NETWARE_FORMAT_DRIVE) {
+
+ p = WorkPath;
+ while (*p != ':' && *p) {
+ p++;
+ }
+
+ if (*p == ':') {
+ p++;
+ }
+
+ sprintf(pFullPath, "%c:\\%s", DriveNumber + 'A', p);
+ }
+
+ /** Build the UNC path (\\server\volume\path) **/
+
+ else if (PathFormat == NETWARE_FORMAT_UNC) {
+
+ p = WorkPath;
+ while (*p != ':' && *p) {
+ p++;
+ }
+
+ if (*p == ':') {
+ *p = '\\';
+ }
+
+ sprintf(pFullPath, "\\\\%s\\%s", ServerName, WorkPath);
+ }
+ }
+ }
+
+ strcpy(WorkPath, Path);
+ /*
+ * Path does not have the relative path (current directory) in it.
+ */
+
+ /** Get the root path if we need to **/
+
+ if (pRootPath) {
+
+ if (Status & NETWARE_LOCAL_FREE_DRIVE) {
+ *pRootPath = 0;
+ }
+ else {
+
+ /** Build the NetWare root path format (volume:) **/
+
+ if (PathFormat == NETWARE_FORMAT_NETWARE) {
+ sprintf(pRootPath, strchr(WorkPath, ':')? "%s" : "%s:", WorkPath);
+ }
+
+ /** Build the server volume root path (server\volume:) **/
+
+ else if (PathFormat == NETWARE_FORMAT_SERVER_VOLUME) {
+ if ( fNDS && !_strcmpi( ServerName, NDSTREE) )
+ sprintf(pRootPath, strchr (WorkPath, ':')? "%s" : "%s:", WorkPath);
+ else
+ sprintf(pRootPath, strchr (WorkPath, ':')? "%s\\%s" : "%s\\%s:", ServerName, WorkPath);
+ }
+
+ /** Build the drive root path (G:\) **/
+
+ else if (PathFormat == NETWARE_FORMAT_DRIVE) {
+ sprintf(pRootPath, "%c:\\", DriveNumber + 'A');
+ }
+
+ /** Build the UNC root path (\\server\volume) **/
+
+ else if (PathFormat == NETWARE_FORMAT_UNC) {
+ sprintf(pRootPath, "\\\\%s\\%s", ServerName, WorkPath);
+ }
+ }
+ }
+
+ /** Get the relative path if we need to **/
+
+ if (pRelativePath) {
+
+ if (Status & NETWARE_LOCAL_FREE_DRIVE) {
+ *pRelativePath = 0;
+ }
+ else {
+ int i;
+ NTGetCurrentDirectory( (unsigned char)DriveNumber, pRelativePath );
+ /*
+ * Skip the drive letter
+ */
+ if ( pRelativePath[0] ) {
+ for ( i = 0; ;i++ ) {
+ pRelativePath[i] = pRelativePath[i+3];
+ if ( !pRelativePath[i] )
+ break;
+ }
+ }
+ }
+ }
+
+ return 0x0000;
+}
diff --git a/private/nw/nwscript/env.c b/private/nw/nwscript/env.c
new file mode 100644
index 000000000..dfece205b
--- /dev/null
+++ b/private/nw/nwscript/env.c
@@ -0,0 +1,352 @@
+/*************************************************************************
+*
+* ENV.C
+*
+* Environment export routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\ENV.C $
+*
+* Rev 1.2 10 Apr 1996 14:22:28 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:53:48 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:24:40 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:06:58 terryt
+* Initial revision.
+*
+* Rev 1.2 25 Aug 1995 16:22:50 terryt
+* Capture support
+*
+* Rev 1.1 23 May 1995 19:36:54 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:10:34 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "nwscript.h"
+
+#define MAX_PATH_LEN 2048
+#define PATH "Path"
+#define LIBPATH "LibPath"
+#define OS2LIBPATH "Os2LibPath"
+
+unsigned char * Path_Value = NULL;
+unsigned char * LibPath_Value = NULL;
+unsigned char * Os2LibPath_Value = NULL;
+
+
+/********************************************************************
+
+ GetOldPaths
+
+Routine Description:
+
+ Save the orginal paths for
+ Path
+ LibPath
+ Os2LibPath
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+GetOldPaths( void )
+{
+ if (!(Path_Value = (unsigned char *)LocalAlloc( LPTR, MAX_PATH_LEN )))
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+ GetEnvironmentVariableA( PATH, Path_Value, MAX_PATH_LEN );
+ if (!(LibPath_Value = (unsigned char *)LocalAlloc( LPTR, MAX_PATH_LEN)))
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+ GetEnvironmentVariableA( LIBPATH, LibPath_Value, MAX_PATH_LEN );
+ if (!(Os2LibPath_Value = (unsigned char *)LocalAlloc( LPTR, MAX_PATH_LEN)))
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+ GetEnvironmentVariableA( OS2LIBPATH, Os2LibPath_Value, MAX_PATH_LEN );
+}
+
+
+/********************************************************************
+
+ AdjustPath
+
+Routine Description:
+
+ Given an old path and a new path, merge the two togther.
+ Basically, the Adjusted path is the old path with the
+ new values at the end, minus any duplicates.
+
+Arguments:
+
+ Value - New path
+ OldPath_Value - Old path
+ AdjustedValue - New value (allocated)
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+AdjustPath( unsigned char * Value,
+ unsigned char * OldPath_Value,
+ unsigned char ** AdjustedValue )
+{
+ unsigned char * tokenPath;
+ unsigned char * clipStart;
+ unsigned char * clipEnd;
+ unsigned char * tokenSearch;
+ unsigned char * tokenNext;
+
+ if (!(*AdjustedValue = (unsigned char *)LocalAlloc( LPTR, MAX_PATH_LEN)))
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+ strncpy( *AdjustedValue, Value, MAX_PATH_LEN );
+
+ if (!(tokenSearch = (unsigned char *)LocalAlloc( LPTR, MAX_PATH_LEN)))
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ (void) LocalFree((HLOCAL) *AdjustedValue) ;
+ return;
+ }
+ strncpy( tokenSearch, OldPath_Value, MAX_PATH_LEN );
+
+ tokenNext = tokenSearch;
+
+ if ( !tokenNext || !tokenNext[0] )
+ tokenPath = NULL;
+ else {
+ tokenPath = tokenNext;
+ tokenNext = strchr( tokenPath, ';' );
+ if ( tokenNext ) {
+ *tokenNext++ = 0;
+ }
+ }
+
+ while ( tokenPath != NULL )
+ {
+ if ( clipStart = strstr( *AdjustedValue, tokenPath ) ) {
+ if ( clipEnd = strchr( clipStart, ';' ) ) {
+ memmove( clipStart, clipEnd + 1, strlen( clipEnd + 1 ) + 1 );
+ }
+ else {
+ clipStart[0] = 0;
+ }
+ }
+
+ if ( !tokenNext || !tokenNext[0] )
+ tokenPath = NULL;
+ else {
+ tokenPath = tokenNext;
+ tokenNext = strchr( tokenPath, ';' );
+ if ( tokenNext ) {
+ *tokenNext++ = 0;
+ }
+ }
+ }
+ (void) LocalFree((HLOCAL) tokenSearch) ;
+
+}
+
+/********************************************************************
+
+ ExportEnv
+
+Routine Description:
+
+ Export environment value to the registry
+
+Arguments:
+
+ EnvString - Environment string
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+ExportEnv( unsigned char * EnvString )
+{
+ HKEY ScriptEnvironmentKey;
+ NTSTATUS Status;
+ unsigned char * Value;
+ unsigned char * ValueName;
+ unsigned char * AdjustedValue = NULL;
+
+ ValueName = EnvString;
+ Value = strchr( EnvString, '=' );
+
+ if ( Value == NULL ) {
+ wprintf(L"Bad Environment string\n");
+
+ return;
+ }
+ Value++;
+
+ if (!(ValueName = (unsigned char *)LocalAlloc( LPTR, Value-EnvString + 1)))
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return;
+ }
+ strncpy( ValueName, EnvString, Value-EnvString - 1 );
+
+ if ( !_strcmpi( ValueName, PATH ) ) {
+ AdjustPath( Value, Path_Value, &AdjustedValue );
+ Value = AdjustedValue;
+ }
+ else if ( !_strcmpi( ValueName, LIBPATH ) ) {
+ AdjustPath( Value, LibPath_Value, &AdjustedValue );
+ Value = AdjustedValue;
+ }
+ else if ( !_strcmpi( ValueName, OS2LIBPATH ) ) {
+ AdjustPath( Value, Os2LibPath_Value, &AdjustedValue );
+ Value = AdjustedValue;
+ }
+
+ Status = RegCreateKeyExW( HKEY_CURRENT_USER,
+ SCRIPT_ENVIRONMENT_VALUENAME,
+ 0,
+ WIN31_CLASS,
+ REG_OPTION_VOLATILE,
+ KEY_WRITE,
+ NULL, // security attr
+ &ScriptEnvironmentKey,
+ NULL
+ );
+
+ if ( NT_SUCCESS(Status)) {
+
+ Status = RegSetValueExA( ScriptEnvironmentKey,
+ ValueName,
+ 0,
+ REG_SZ,
+ (LPVOID) Value,
+ strlen( Value ) + 1
+ );
+ }
+ else {
+ wprintf(L"Cannot create registry key\n");
+ }
+
+ (void) LocalFree((HLOCAL) ValueName) ;
+
+ if ( AdjustedValue )
+ (void) LocalFree((HLOCAL) AdjustedValue) ;
+
+ RegCloseKey( ScriptEnvironmentKey );
+}
+
+/********************************************************************
+
+ ExportCurrentDirectory
+
+Routine Description:
+
+ Return the first non-local drive
+
+Arguments:
+
+ DriveNum - Number of drive 1-26
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+ExportCurrentDirectory( int DriveNum )
+{
+ char DriveName[10];
+ HKEY ScriptEnvironmentKey;
+ NTSTATUS Status;
+ char CurrentPath[MAX_PATH_LEN];
+
+ strcpy( DriveName, "=A:" );
+
+ DriveName[1] += (DriveNum - 1);
+
+ if ( NTGetCurrentDirectory( (unsigned char)(DriveNum - 1), CurrentPath ) )
+ return;
+
+ Status = RegCreateKeyExW( HKEY_CURRENT_USER,
+ SCRIPT_ENVIRONMENT_VALUENAME,
+ 0,
+ WIN31_CLASS,
+ REG_OPTION_VOLATILE,
+ KEY_WRITE,
+ NULL, // security attr
+ &ScriptEnvironmentKey,
+ NULL
+ );
+
+ if ( NT_SUCCESS(Status)) {
+
+ Status = RegSetValueExA( ScriptEnvironmentKey,
+ DriveName,
+ 0,
+ REG_SZ,
+ (LPVOID) CurrentPath,
+ strlen( CurrentPath ) + 1
+ );
+ }
+ else {
+ wprintf(L"Cannot open registry key\n");
+ }
+
+ RegCloseKey( ScriptEnvironmentKey );
+
+}
+
+
+/********************************************************************
+
+ ExportCurrentDrive
+
+Routine Description:
+
+ Export current drive to registry
+ NOT IMPLEMENTED
+
+Arguments:
+
+ DriveNum - drive number
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+ExportCurrentDrive( int DriveNum )
+{
+ /*
+ * Don't know if we want to do this or how.
+ */
+}
diff --git a/private/nw/nwscript/helpers.c b/private/nw/nwscript/helpers.c
new file mode 100644
index 000000000..9f504490f
--- /dev/null
+++ b/private/nw/nwscript/helpers.c
@@ -0,0 +1,96 @@
+/******************************************************************************
+*
+* HELPERS.C
+*
+* Various helper functions.
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\HELPERS.C $
+*
+* Rev 1.1 22 Dec 1995 14:24:48 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:07:02 terryt
+* Initial revision.
+*
+* Rev 1.1 25 Aug 1995 16:22:56 terryt
+* Capture support
+*
+* Rev 1.0 15 May 1995 19:10:38 terryt
+* Initial revision.
+*
+*
+*******************************************************************************/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+
+#include <windows.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+
+#include "nwscript.h"
+
+
+/*******************************************************************************
+ *
+ * DisplayMessage
+ * Display a message with variable arguments. Message
+ * format string comes from the application resources.
+ *
+ * ENTRY:
+ * nID (input)
+ * Resource ID of the format string to use in the message.
+ * ... (input)
+ * Optional additional arguments to be used with format string.
+ *
+ * EXIT:
+ *
+ ******************************************************************************/
+
+VOID
+DisplayMessage( unsigned int nID, ... )
+{
+ WCHAR sz1[512];
+
+ va_list args;
+ va_start( args, nID );
+
+ if ( LoadString( NULL, nID, sz1, 512 ) ) {
+
+ setlocale(LC_ALL,".ACP") ;
+ vwprintf( sz1, args );
+ setlocale(LC_ALL,".OCP") ;
+
+ }
+
+ va_end(args);
+
+} /* DisplayMessage() */
+
+
+/*******************************************************************************
+ *
+ * DisplayOemString
+ * Display an OEM string
+ *
+ * ENTRY:
+ * string: string to display
+ *
+ * EXIT:
+ *
+ ******************************************************************************/
+
+VOID
+DisplayOemString( char *string )
+{
+ // this will print % in strings correctly.
+ printf( "%s", string );
+
+} /* DisplayAnsiString() */
+
+
diff --git a/private/nw/nwscript/inc/common.h b/private/nw/nwscript/inc/common.h
new file mode 100644
index 000000000..14764853d
--- /dev/null
+++ b/private/nw/nwscript/inc/common.h
@@ -0,0 +1,195 @@
+
+/*************************************************************************
+*
+* COMMON.H
+*
+* Common header file
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\INC\VCS\COMMON.H $
+*
+* Rev 1.3 22 Dec 1995 14:20:06 terryt
+* Add Microsoft headers
+*
+* Rev 1.2 22 Nov 1995 15:44:26 terryt
+* Use proper NetWare user name call
+*
+* Rev 1.1 20 Nov 1995 15:18:46 terryt
+* Context and capture changes
+*
+* Rev 1.0 15 Nov 1995 18:05:30 terryt
+* Initial revision.
+*
+* Rev 1.2 25 Aug 1995 17:03:32 terryt
+* CAPTURE support
+*
+* Rev 1.1 26 Jul 1995 16:01:12 terryt
+* Get rid of unneccessary externs
+*
+* Rev 1.0 15 May 1995 19:09:28 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <stdio.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <nds.h>
+#include <ndsapi32.h>
+#include <nwapi32.h>
+
+#include "dbcs.h"
+#include "inc\nwlibs.h"
+
+#include "nwscript.h"
+
+
+#define MAX_NAME_LEN 48
+#define MAX_PASSWORD_LEN 128
+#define MAX_PATH_LEN 304 //From NW programmer's guide p268.
+
+/* for map only */
+#define MAX_VOLUME_LEN 256 // 17 for 3X
+#define MAX_DIR_PATH_LEN 256
+
+/* for capture only */
+#define MAX_JOB_NAME_LEN 32
+#define MAX_QUEUE_NAME_LEN 1024
+#define MAX_BANNER_USER_NAME 13
+
+/* for common only */
+#define PATH_SEPERATOR ";"
+
+
+/*
+ Function definations
+ */
+/* used by login.c and script.c */
+void BreakOff(void);
+void BreakOn(void);
+
+/* used by common setpass*/
+void xstrupr(char *buffer);
+void ReadPassword(char * Password);
+
+/* used by map attach login*/
+int CAttachToFileServer(char *ServerName, unsigned int *pConn, int * pbAlreadyAttached);
+int Login(char *UserName, char *ServerName, char *Password, int bReadPassword);
+
+/* used by map attach login*/
+int ReadName (char * Name);
+
+/* used by map login */
+void DisplayError(int error ,char *functionName);
+char * GetDosEnv1(void);
+char * NWGetPath(void);
+int GetRestEnvLen (char *lpRest);
+
+int MemorySegmentLargeEnough (int nInsertByte);
+int IsSearchDrive(int driveNum);
+int GetDriveFromSearchNumber (int searchNumber);
+
+/* used by login logout*/
+void SetLoginDirectory (PBYTE);
+
+/* used by all */
+int Map (char * buffer);
+void DisplayMapping(void);
+int CGetDefaultConnectionID ( unsigned int * pConn );
+int GetConnectionInfo (unsigned int conn,
+ char * serverName,
+ char * userName,
+ unsigned int * pconnNum,
+ unsigned char * loginTime);
+
+extern char * LOGIN_NAME;
+extern char *NDS_FULL_NAME;
+extern char *REQUESTER_CONTEXT;
+extern char *TYPED_USER_NAME;
+extern PWCHAR TYPED_USER_NAME_w;
+extern PBYTE NDSTREE;
+extern PWCHAR NDSTREE_w;
+extern UNICODE_STRING NDSTREE_u;
+extern PBYTE PREFERRED_SERVER;
+
+/*
+ String definitions.
+ */
+extern char *__Day__[7];
+extern char *__Month__[12];
+extern char *__AMPM__[2];
+extern char *__GREETING__[3];
+
+extern char __DEL__[];
+extern char __REM__[];
+extern char __INS__[];
+extern char __ROOT__[];
+extern char __NEXT__[];
+
+extern char __AUTOENDCAP__[];
+extern char __BANNER__[];
+extern char __COPIES__[];
+extern char __CREATE__[];
+extern WCHAR __DISABLED__[];
+extern WCHAR __ENABLED__[];
+extern WCHAR __YES__[];
+extern WCHAR __NO__[];
+extern WCHAR __SECONDS__[];
+extern WCHAR __CONVERT_TO_SPACE__[];
+extern WCHAR __NO_CONVERSION__[];
+extern WCHAR __NOTIFY_USER__[];
+extern WCHAR __NOT_NOTIFY_USER__[];
+extern WCHAR __NONE__[];
+extern char __FORMFEED__[];
+extern char __FORM__[];
+extern char __JOB_DESCRIPTION__[];
+extern char __JOB__[];
+extern char __KEEP__[];
+extern char __LOCAL__[];
+extern char __LOCAL_2__[];
+extern char __LOCAL_3__[];
+extern char __NAME__[];
+extern char __NOAUTOENDCAP__[];
+extern char __NOBANNER__[];
+extern char __NOFORMFEED__[];
+extern char __NONOTIFY__[];
+extern char __NOTABS__[];
+extern char __NOTIFY__[];
+extern char __QUEUE__[];
+extern char __PRINTER__[];
+extern char __OPT_NO__[];
+extern char __SERVER__[];
+extern char __SHORT_FOR_AUTOENDCAP__[];
+extern char __SHORT_FOR_BANNER__[];
+extern char __SHORT_FOR_COPIES__[];
+extern char __SHORT_FOR_CREATE__[];
+extern char __SHORT_FOR_FORMFEED__[];
+extern char __SHORT_FOR_FORM__[];
+extern char __SHORT_FOR_JOB__[];
+extern char __SHORT_FOR_KEEP__[];
+extern char __SHORT_FOR_LOCAL__[];
+extern char __SHORT_FOR_NAME__[];
+extern char __SHORT_FOR_NOAUTOENDCAP__[];
+extern char __SHORT_FOR_NOBANNER__[];
+extern char __SHORT_FOR_NOFORMFEED__[];
+extern char __SHORT_FOR_NONOTIFY__[];
+extern char __SHORT_FOR_NOTABS__[];
+extern char __SHORT_FOR_NOTIFY__[];
+extern char __SHORT_FOR_QUEUE__[];
+extern char __SHORT_FOR_PRINTER__[];
+extern char __SHORT_FOR_SERVER__[];
+extern char __SHORT_FOR_TABS__[];
+extern char __SHORT_FOR_TIMEOUT__[];
+extern char __SHOW__[];
+extern char __TABS__[];
+extern char __TIMEOUT__[];
+
+extern unsigned int CaptureStringsLoaded;
+extern unsigned int fNDS;
diff --git a/private/nw/nwscript/inc/dbcs.h b/private/nw/nwscript/inc/dbcs.h
new file mode 100644
index 000000000..2fb4a5b5b
--- /dev/null
+++ b/private/nw/nwscript/inc/dbcs.h
@@ -0,0 +1,26 @@
+
+/*************************************************************************
+*
+* DBCS.H
+*
+* DBCS header file
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\INC\VCS\DBCS.H $
+*
+* Rev 1.1 22 Dec 1995 14:20:14 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:05:32 terryt
+* Initial revision.
+*
+* Rev 1.1 25 Aug 1995 17:03:40 terryt
+* CAPTURE support
+*
+* Rev 1.0 15 May 1995 19:09:32 terryt
+* Initial revision.
+*
+*************************************************************************/
+unsigned char *NWAnsiNext(unsigned char *puch);
+unsigned char *NWAnsiPrev(unsigned char *psz, unsigned char *puch);
diff --git a/private/nw/nwscript/inc/ntnw.h b/private/nw/nwscript/inc/ntnw.h
new file mode 100644
index 000000000..a89e15720
--- /dev/null
+++ b/private/nw/nwscript/inc/ntnw.h
@@ -0,0 +1,46 @@
+
+/*************************************************************************
+*
+* NTNW.H
+*
+* NT specific NetWare defines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\INC\VCS\NTNW.H $
+*
+* Rev 1.1 22 Dec 1995 14:20:20 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:05:34 terryt
+* Initial revision.
+*
+* Rev 1.0 15 May 1995 19:09:36 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+/*
+ * This must be kept in sync with the NWAPI32 library. This are
+ * internal data structures and routines.
+ */
+typedef struct _NWC_SERVER_INFO {
+ HANDLE hConn ;
+ UNICODE_STRING ServerString ;
+} NWC_SERVER_INFO, *PNWC_SERVER_INFO ;
+
+extern NTSTATUS
+NwlibMakeNcp(
+ IN HANDLE DeviceHandle,
+ IN ULONG FsControlCode,
+ IN ULONG RequestBufferSize,
+ IN ULONG ResponseBufferSize,
+ IN PCHAR FormatString,
+ ... // Arguments to FormatString
+ );
+
+DWORD szToWide( LPWSTR lpszW, LPCSTR lpszC, INT nSize );
+DWORD WideTosz( LPSTR lpszC, LPWSTR lpszW, INT nSize );
+
+extern TCHAR NW_PROVIDER[60];
+
diff --git a/private/nw/nwscript/inc/nwlibs.h b/private/nw/nwscript/inc/nwlibs.h
new file mode 100644
index 000000000..64a187e52
--- /dev/null
+++ b/private/nw/nwscript/inc/nwlibs.h
@@ -0,0 +1,371 @@
+
+/*************************************************************************
+*
+* NWLIBS.H
+*
+* Prototypes
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\INC\VCS\NWLIBS.H $
+*
+* Rev 1.1 22 Dec 1995 14:20:28 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:05:36 terryt
+* Initial revision.
+*
+* Rev 1.1 25 Aug 1995 17:03:46 terryt
+* CAPTURE support
+*
+* Rev 1.0 15 May 1995 19:09:40 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+/*++
+
+Copyright (c) 1994 Micro Computer Systems, Inc.
+
+Module Name:
+
+ nwlibs\nwlibs.h
+
+Abstract:
+
+ NW Libs prototypes.
+
+Author:
+
+ Shawn Walker (v-swalk) 10-10-1994
+
+Revision History:
+
+--*/
+
+#ifndef _NWLIBS_H_
+#define _NWLIBS_H_
+
+
+/*++
+*******************************************************************
+ NetWare defaults
+*******************************************************************
+--*/
+#define NCP_BINDERY_OBJECT_NAME_LENGTH 48
+#define NCP_SERVER_NAME_LENGTH NCP_BINDERY_OBJECT_NAME_LENGTH
+
+#define NCP_MAX_PATH_LENGTH 255
+#define NCP_VOLUME_LENGTH 256 // 16 in 3X
+
+
+/*++
+*******************************************************************
+ Defines for GetDrive Status
+*******************************************************************
+--*/
+
+#define NETWARE_UNMAPPED_DRIVE 0x0000
+#define NETWARE_FREE_DRIVE 0x0000
+#define NETWARE_LOCAL_FREE_DRIVE 0x0800
+#define NETWARE_LOCAL_DRIVE 0x1000
+#define NETWARE_NETWORK_DRIVE 0x2000
+#define NETWARE_LITE_DRIVE 0x4000
+#define NETWARE_PNW_DRIVE 0x4000
+#define NETWARE_NETWARE_DRIVE 0x8000
+
+#define NETWARE_FORMAT_NETWARE 0
+#define NETWARE_FORMAT_SERVER_VOLUME 1
+#define NETWARE_FORMAT_DRIVE 2
+#define NETWARE_FORMAT_UNC 3
+
+#define NCP_JOB_DESCRIPTION_LENGTH 50
+#define NCP_BANNER_TEXT_LENGTH 13
+#define NCP_FORM_NAME_LENGTH 13
+#define NCP_QUEUE_NAME_LENGTH 65
+
+#define CAPTURE_FLAG_PRINT_BANNER 0x80
+#define CAPTURE_FLAG_EXPAND_TABS 0x40
+#define CAPTURE_FLAG_NOTIFY 0x10
+#define CAPTURE_FLAG_NO_FORMFEED 0x08
+#define CAPTURE_FLAG_KEEP 0x04
+#define DEFAULT_PRINT_FLAGS 0xC0
+#define DEFAULT_BANNER_TEXT "LPT:"
+
+typedef struct _NETWARE_CAPTURE_FLAGS_RW {
+ unsigned char JobDescription[NCP_JOB_DESCRIPTION_LENGTH];
+ unsigned char JobControlFlags;
+ unsigned char TabSize;
+ unsigned short NumCopies;
+ unsigned short PrintFlags;
+ unsigned short MaxLines;
+ unsigned short MaxChars;
+ unsigned char FormName[NCP_FORM_NAME_LENGTH];
+ unsigned char Reserved1[9];
+ unsigned short FormType;
+ unsigned char BannerText[NCP_BANNER_TEXT_LENGTH];
+ unsigned char Reserved2;
+ unsigned short FlushCaptureTimeout;
+ unsigned char FlushCaptureOnClose;
+} NETWARE_CAPTURE_FLAGS_RW, *PNETWARE_CAPTURE_FLAGS_RW, *LPNETWARE_CAPTURE_FLAGS_RW;
+
+typedef struct _NETWARE_CAPTURE_FLAGS_RO {
+ unsigned short ConnectionID;
+ unsigned short SetupStringMaxLen;
+ unsigned short ResetStringMaxLen;
+ unsigned char LPTCaptureFlag;
+ unsigned char FileCaptureFlag;
+ unsigned char TimingOutFlag;
+ unsigned char InProgress;
+ unsigned char PrintQueueFlag;
+ unsigned char PrintJobValid;
+ unsigned char QueueName[NCP_QUEUE_NAME_LENGTH];
+ unsigned char ServerName[NCP_SERVER_NAME_LENGTH];
+} NETWARE_CAPTURE_FLAGS_RO, *PNETWARE_CAPTURE_FLAGS_RO, *LPNETWARE_CAPTURE_FLAGS_RO;
+
+#define NETWARE_CAPTURE_FLAGS_RO_SIZE sizeof(NETWARE_CAPTURE_FLAGS_RO)
+#define NETWARE_CAPTURE_FLAGS_RW_SIZE sizeof(NETWARE_CAPTURE_FLAGS_RW)
+
+#define PS_FORM_NAME_SIZE 12
+#define PS_BANNER_NAME_SIZE 12
+#define PS_BANNER_FILE_SIZE 12
+#define PS_DEVICE_NAME_SIZE 32
+#define PS_MODE_NAME_SIZE 32
+
+#define PS_BIND_NAME_SIZE NCP_BINDERY_OBJECT_NAME_LENGTH
+#define PS_MAX_NAME_SIZE 514
+
+/** Flags for the PS_JOB_REC structure PrintJobFlag field **/
+
+#define PS_JOB_EXPAND_TABS 0x00000001 /* File type:0=Stream 1=Tab */
+#define PS_JOB_NO_FORMFEED 0x00000002 /* Formfeed tail:0=Yes 1=No */
+#define PS_JOB_NOTIFY 0x00000004 /* Notify:0=No 1=Yes */
+#define PS_JOB_PRINT_BANNER 0x00000008 /* Banner:0=No 1=Yes */
+#define PS_JOB_AUTO_END 0x00000010 /* Auto endcap:0=No 1=Yes */
+#define PS_JOB_TIMEOUT 0x00000020 /* Enable T.O.:0=No 1=Yes */
+
+#define PS_JOB_ENV_DS 0x00000040 /* Use D.S. Environment */
+#define PS_JOB_ENV_MASK 0x000001C0 /* Bindery vs. D.S. Mask */
+
+#define PS_JOB_DS_PRINTER 0x00000200 /* D.S. Printer not Queue */
+#define PS_JOB_PRINTER_MASK 0x00000E00 /* D.S. Printer vs. Queue */
+
+/** Default Flags **/
+
+#define PS_JOB_DEFAULT (NWPS_JOB_PRINT_BANNER | NWPS_JOB_AUTO_END)
+#define PS_JOB_DEFAULT_COPIES 1 /* Default Number of Copies */
+#define PS_JOB_DEFAULT_TAB 8 /* Default Tab Expansion */
+
+typedef struct _PS_JOB_RECORD {
+ DWORD PrintJobFlag;
+ SHORT Copies;
+ SHORT TimeOutCount;
+ UCHAR TabSize;
+ UCHAR LocalPrinter;
+ CHAR FormName[PS_FORM_NAME_SIZE + 2];
+ CHAR Name[PS_BANNER_NAME_SIZE + 2];
+ CHAR BannerName[PS_BANNER_FILE_SIZE + 2];
+ CHAR Device[PS_DEVICE_NAME_SIZE + 2];
+ CHAR Mode[PS_MODE_NAME_SIZE + 2];
+ union {
+ struct {
+ /** Pad structures on even boundries **/
+
+ CHAR FileServer[PS_BIND_NAME_SIZE + 2];
+ CHAR PrintQueue[PS_BIND_NAME_SIZE + 2];
+ CHAR PrintServer[PS_BIND_NAME_SIZE + 2];
+ } NonDS;
+ CHAR DSObjectName[PS_MAX_NAME_SIZE];
+ } u;
+ UCHAR Reserved[392];
+} PS_JOB_RECORD, *PPS_JOB_RECORD;
+
+#define PS_JOB_RECORD_SIZE sizeof(PS_JOB_RECORD)
+
+
+/*++
+*******************************************************************
+ FUCNTION PROTOTYPES
+*******************************************************************
+--*/
+
+/** ATTACH.C **/
+
+unsigned int
+AttachToFileServer(
+ unsigned char *pServerName,
+ unsigned int *pNewConnectionId
+ );
+
+unsigned int
+DetachFromFileServer(
+ unsigned int ConnectionId
+ );
+
+/** NCP.C **/
+
+unsigned int
+GetBinderyObjectID(
+ unsigned int ConnectionHandle,
+ char *pObjectName,
+ unsigned short ObjectType,
+ unsigned long *pObjectId
+ );
+
+
+/** CONNECT.C **/
+
+unsigned int
+GetDefaultConnectionID(
+ unsigned int *pConnectionHandle
+ );
+
+unsigned int
+GetConnectionHandle(
+ unsigned char *pServerName,
+ unsigned int *pConnectionHandle
+ );
+
+unsigned int
+GetConnectionNumber(
+ unsigned int ConnectionHandle,
+ unsigned int *pConnectionNumber
+ );
+
+unsigned int
+GetFileServerName(
+ unsigned int ConnectionHandle,
+ char *pServerName
+ );
+
+unsigned int
+GetInternetAddress(
+ unsigned int ConnectionHandle,
+ unsigned int ConnectionNumber,
+ unsigned char *pInternetAddress
+ );
+
+/** DRIVE.C **/
+
+unsigned int
+GetDriveStatus(
+ unsigned short DriveNumber,
+ unsigned short PathFormat,
+ unsigned short *pStatus,
+ unsigned int *pConnectionHandle,
+ unsigned char *pRootPath,
+ unsigned char *pRelativePath,
+ unsigned char *pFullPath
+ );
+
+unsigned int
+GetFirstDrive(
+ unsigned short *pFirstDrive
+ );
+
+unsigned int
+ParsePath(
+ unsigned char *pPath,
+ unsigned char *pServerName, //OPTIONAL
+ unsigned char *pVolumeName, //OPTIONAL
+ unsigned char *pDirPath //OPTIONAL
+ );
+
+unsigned int
+SetDriveBase(
+ unsigned short DriveNumber,
+ unsigned char *ServerName,
+ unsigned int DirHandle,
+ unsigned char *pDirPath
+ );
+
+unsigned int
+DeleteDriveBase(
+ unsigned short DriveNumber
+ );
+
+unsigned int
+GetDirectoryPath(
+ unsigned char ConnectionHandle,
+ unsigned char Handle,
+ unsigned char *pPath
+ );
+
+unsigned int
+IsDriveRemote(
+ unsigned char DriveNumber,
+ unsigned int *pRemote
+ );
+
+/** CAPTURE.C **/
+
+unsigned int
+EndCapture(
+ unsigned char LPTDevice
+ );
+
+#define PS_ERR_BAD_VERSION 0x7770
+#define PS_ERR_GETTING_DEFAULT 0x7773
+#define PS_ERR_OPENING_DB 0x7774
+#define PS_ERR_READING_DB 0x7775
+#define PS_ERR_READING_RECORD 0x7776
+#define PS_ERR_INTERNAL_ERROR 0x7779
+#define PS_ERR_NO_DEFAULT_SPECIFIED 0x777B
+
+unsigned int
+PSJobGetDefault(
+ unsigned int ConnectionHandle,
+ unsigned short SearchFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord
+ );
+
+unsigned int
+PSJobRead(
+ unsigned int ConnectionHandle,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord
+ );
+
+unsigned int
+PS40JobGetDefault(
+ unsigned int NDSCaptureFlag,
+ unsigned short SearchFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord
+ );
+
+unsigned int
+PS40JobRead(
+ unsigned int NDSCaptureFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord
+ );
+
+unsigned int
+GetCaptureFlags(
+ unsigned char LPTDevice,
+ PNETWARE_CAPTURE_FLAGS_RW pCaptureFlagsRW,
+ PNETWARE_CAPTURE_FLAGS_RO pCaptureFlagsRO
+ );
+
+unsigned int
+StartQueueCapture(
+ unsigned int ConnectionHandle,
+ unsigned char LPTDevice,
+ unsigned char *pServerName,
+ unsigned char *pQueueName
+ );
+
+unsigned int
+GetDefaultPrinterQueue (
+ unsigned int ConnectionHandle,
+ unsigned char *pServerName,
+ unsigned char *pQueueName
+ );
+
+#endif /* _NWLIBS_H_ */
diff --git a/private/nw/nwscript/inc/nwscript.h b/private/nw/nwscript/inc/nwscript.h
new file mode 100644
index 000000000..d930e7818
--- /dev/null
+++ b/private/nw/nwscript/inc/nwscript.h
@@ -0,0 +1,321 @@
+/******************************************************************************
+*
+* NWSCRIPT.H
+*
+* This module contains typedefs and defines required for the
+* NetWare script utility.
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\INC\VCS\NWSCRIPT.H $
+*
+* Rev 1.10 18 Apr 1996 16:53:02 terryt
+* Various enhancements
+*
+* Rev 1.9 10 Apr 1996 14:22:36 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.10 12 Mar 1996 19:42:52 terryt
+* Relative NDS name support
+*
+* Rev 1.9 07 Mar 1996 18:34:46 terryt
+* Misc fixes
+*
+* Rev 1.8 22 Jan 1996 16:44:02 terryt
+* Add automatic map attaches
+*
+* Rev 1.7 08 Jan 1996 13:58:34 terryt
+* Correct NDS Preferred Server
+*
+* Rev 1.6 05 Jan 1996 17:19:08 terryt
+* Ensure context is the correct login default
+*
+* Rev 1.5 04 Jan 1996 18:58:34 terryt
+* Bug fixes reported by MS
+*
+* Rev 1.4 22 Dec 1995 14:20:34 terryt
+* Add Microsoft headers
+*
+* Rev 1.3 28 Nov 1995 17:13:56 terryt
+* Cleanup resource file
+*
+* Rev 1.2 22 Nov 1995 15:44:34 terryt
+* Use proper NetWare user name call
+*
+* Rev 1.1 20 Nov 1995 16:11:34 terryt
+* Context and capture changes
+*
+* Rev 1.0 15 Nov 1995 18:05:38 terryt
+* Initial revision.
+*
+* Rev 1.5 25 Aug 1995 17:03:52 terryt
+* CAPTURE support
+*
+* Rev 1.4 18 Jul 1995 16:07:52 terryt
+* Screen out capture commands
+*
+* Rev 1.3 17 Jul 1995 09:43:02 terryt
+* Use Microsoft name for environment
+*
+* Rev 1.2 23 Jun 1995 09:49:58 terryt
+* Add error message for mapping over MS network drive
+*
+* Rev 1.1 23 May 1995 19:38:14 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:09:42 terryt
+* Initial revision.
+*
+******************************************************************************/
+
+
+#define SCRIPT_ENVIRONMENT_VALUENAME L"Volatile Environment"
+#define REGISTRY_PROVIDER L"System\\CurrentControlSet\\Services\\NWCWorkstation\\networkProvider"
+#define REGISTRY_PROVIDERNAME L"Name"
+
+typedef enum SYNTAX
+{
+ NDSI_UNKNOWN, /* 0 */
+ NDSI_DIST_NAME, /* 1 */
+ NDSI_CE_STRING, /* 2 */
+ NDSI_CI_STRING, /* 3 */
+ NDSI_PR_STRING, /* 4 */
+ NDSI_NU_STRING, /* 5 */
+ NDSI_CI_LIST, /* 6 */
+ NDSI_BOOLEAN, /* 7 */
+ NDSI_INTEGER, /* 8 */
+ NDSI_OCTET_STRING, /* 9 */
+ NDSI_TEL_NUMBER, /* 10 */
+ NDSI_FAX_NUMBER, /* 11 */
+ NDSI_NET_ADDRESS, /* 12 */
+ NDSI_OCTET_LIST, /* 13 */
+ NDSI_EMAIL_ADDRESS, /* 14 */
+ NDSI_PATH, /* 15 */
+ NDSI_REPLICA_POINTER, /* 16 */
+ NDSI_OBJECT_ACL, /* 17 */
+ NDSI_PO_ADDRESS, /* 18 */
+ NDSI_TIMESTAMP, /* 19 */
+ NDSI_CLASS_NAME, /* 20 */
+ NDSI_STREAM, /* 21 */
+ NDSI_COUNTER, /* 22 */
+ NDSI_BACK_LINK, /* 23 */
+ NDSI_TIME, /* 24 */
+ NDSI_TYPED_NAME, /* 25 */
+ NDSI_HOLD, /* 26 */
+ NDSI_INTERVAL, /* 27 */
+ NDSI_TAX_COUNT /* 28 */
+} SYNTAX;
+
+#define DSCL_AFP_SERVER "AFP Server"
+#define DSCL_ALIAS "Alias"
+#define DSCL_BINDERY_OBJECT "Bindery Object"
+#define DSCL_BINDERY_QUEUE "Bindery Queue"
+#define DSCL_COMPUTER "Computer"
+#define DSCL_COUNTRY "Country"
+#define DSCL_DEVICE "Device"
+#define DSCL_DIRECTORY_MAP "Directory Map"
+#define DSCL_EXTERNAL_ENTITY "External Entity"
+#define DSCL_GROUP "Group"
+#define DSCL_LIST "List"
+#define DSCL_LOCALITY "Locality"
+#define DSCL_MESSAGE_ROUTING_GROUP "Message Routing Group"
+#define DSCL_MESSAGING_SERVER "Messaging Server"
+#define DSCL_NCP_SERVER "NCP Server"
+#define DSCL_ORGANIZATION "Organization"
+#define DSCL_ORGANIZATIONAL_PERSON "Organizational Person"
+#define DSCL_ORGANIZATIONAL_ROLE "Organizational Role"
+#define DSCL_ORGANIZATIONAL_UNIT "Organizational Unit"
+#define DSCL_PARTITION "Partition"
+#define DSCL_PERSON "Person"
+#define DSCL_PRINT_SERVER "Print Server"
+#define DSCL_PRINTER "Printer"
+#define DSCL_PROFILE "Profile"
+#define DSCL_QUEUE "Queue"
+#define DSCL_RESOURCE "Resource"
+#define DSCL_SERVER "Server"
+#define DSCL_TOP "Top"
+#define DSCL_UNKNOWN "Unknown"
+#define DSCL_USER "User"
+#define DSCL_VOLUME "Volume"
+
+#define DSAT_HOST_SERVER "Host Server"
+#define DSAT_HOST_RESOURCE_NAME "Host Resource Name"
+#define DSAT_PATH "Path"
+
+void ConvertUnicodeToAscii( PVOID );
+
+void NTGetTheDate( unsigned int *, unsigned char *, unsigned char * );
+void NTGetVersionOfShell( char *, unsigned char *, unsigned char *, unsigned char * );
+void NTBreakOff( void );
+void NTBreakOn( void );
+unsigned short NTNetWareDriveStatus( unsigned short );
+unsigned int NTGetNWDrivePath( unsigned short, unsigned char *, unsigned char * );
+char * NTNWtoUNCFormat( char * );
+unsigned int NTLoginToFileServer( char *, char *, char * );
+unsigned int NTAttachToFileServer( unsigned char *, unsigned int * );
+unsigned int NTIsConnected( unsigned char * );
+unsigned int NTSetDriveBase( unsigned char *, unsigned char *, unsigned char * );
+unsigned int NTGetUserID( unsigned int, unsigned long * );
+unsigned int NTIsNetWareDrive( unsigned int );
+void NTInitProvider( void );
+void DisplayMessage( unsigned int, ... );
+void DisplayOemString( char * );
+void ExportEnv( unsigned char * );
+void ExportCurrentDirectory( int );
+void ExportCurrentDrive( int );
+void GetOldPaths( void );
+void NTPrintExtendedError( void );
+unsigned int NTGetCurrentDirectory( unsigned char, unsigned char * );
+void Capture( char ** argv, unsigned int );
+unsigned int ConverNDSPathToNetWarePathA(char *, char *, char *);
+
+#define CONTEXT_MAX 256
+#define ATTRBUFSIZE 2048
+#define NDS_NAME_CHARS 1024
+
+
+unsigned int NDSInitUserProperty( void );
+unsigned int NDSGetUserProperty( PBYTE, PBYTE Data, unsigned int, SYNTAX *, unsigned int * );
+void NDSGetVar ( PBYTE, PBYTE, unsigned int );
+unsigned int NDSChangeContext( PBYTE );
+unsigned int NDSGetContext( PBYTE, unsigned int );
+unsigned int Is40Server( unsigned int );
+unsigned int NDSfopenStream ( PBYTE, PBYTE, PHANDLE, unsigned int * );
+unsigned int IsMemberOfNDSGroup( PBYTE );
+unsigned int NDSGetProperty ( PBYTE, PBYTE, PBYTE, unsigned int, unsigned int * );
+unsigned int NDSTypeless( LPSTR, LPSTR );
+void CleanupExit( int );
+void NDSCleanup( void );
+int NTGetNWUserName( PWCHAR, PWCHAR, int );
+unsigned int NDSGetClassName( LPSTR, LPSTR );
+
+unsigned int NDSCanonicalizeName( PBYTE, PBYTE, int, int );
+
+#define LIST_3X_SERVER 1
+#define LIST_4X_SERVER 2
+
+BOOL IsServerInAttachList( char *, unsigned int );
+void AddServerToAttachList( char *, unsigned int );
+int DoAttachProcessing( char * );
+
+#define FLAGS_LOCAL_CONTEXT 0x1
+#define FLAGS_NO_CONTEXT 0x2
+#define FLAGS_TYPED_NAMES 0x4
+
+unsigned int NDSAbbreviateName( DWORD, LPSTR, LPSTR );
+
+/*
+ * Resource string IDs
+ */
+#define IDR_ERROR 100
+#define IDR_NO_DEFAULT_CONNECTION 101
+#define IDR_NO_KNOWN_FILE_SERVER 102
+#define IDR_LOCAL_DRIVE 103
+#define IDR_NETWARE_DRIVE 104
+#define IDR_DASHED_LINE 105
+#define IDR_LOCAL_SEARCH 106
+#define IDR_NETWARE_SEARCH 107
+#define IDR_NOT_ENOUGH_MEMORY 108
+#define IDR_PASSWORD 109
+#define IDR_ATTACHED 110
+#define IDR_ACCESS_DENIED 111
+#define IDR_UNAUTHORIZED_LOGIN_TIME 112
+#define IDR_LOGIN_DENIED_NO_CONNECTION 113
+#define IDR_UNAUTHORIZED_LOGIN_STATION 114
+#define IDR_ACCOUNT_DISABLED 115
+#define IDR_PASSWORD_EXPRIED_NO_GRACE 116
+#define IDR_MAP_NOT_ATTACHED_SERVER 117
+#define IDR_MAP_USAGE 118
+#define IDR_UNDEFINED 119
+#define IDR_DIRECTORY_NOT_FOUND 120
+#define IDR_VOLUME_NOT_EXIST 121
+#define IDR_WRONG_DRIVE 122
+#define IDR_DEL_DRIVE 123
+#define IDR_DEL_SEARCH_DRIVE 124
+#define IDR_SEARCH_DRIVE_NOT_EXIST 125
+#define IDR_NOT_NETWORK_DRIVE 126
+#define IDR_NO_DRIVE_AVAIL 127
+#define IDR_INVALID_PATH 128
+#define IDR_CAN_NOT_CHANGE_DRIVE 129
+#define IDR_MAP_INVALID_PATH 130
+#define IDR_MAP_FAILED 131
+#define IDR_NO_SCRIPT_FILE 132
+#define IDR_STRIKE_KEY 133
+#define IDR_CANNOT_EXECUTE 134
+#define IDR_ENOENT 135
+#define IDR_EXIT_NOT_SUPPORTED 136
+#define IDR_IF_TOO_DEEP 137
+#define IDR_SCRIPT_ERROR 138
+#define IDR_ORIGINAL_LINE_WAS 139
+#define IDR_BAD_COMMAND 140
+#define IDR_LABEL_NOT_FOUND 141
+#define IDR_NO_VOLUME 142
+#define IDR_ERROR_DURING 143
+#define IDR_MAP_ERROR 144
+#define IDR_ENTER_SERVER_NAME 145
+#define IDR_ENTER_LOGIN_NAME 146
+#define IDR_ERROR_SET_DEFAULT_DRIVE 147
+#define IDR_ERROR_OPEN_SCRIPT 148
+#define IDR_DIVIDE_BY_ZERO 149
+#define IDR_NEWLINE 150
+#define IDR_SERVER_USER 151
+#define IDR_NON_NETWARE_NETWORK_DRIVE 152
+#define IDR_CAPTURE_USAGE 153
+#define IDR_COPIES_EXPECTED 154
+#define IDR_COPIES_OUTOF_RANGE 155
+#define IDR_FILE_CAPTURE_UNSUPPORTED 156
+#define IDR_FORM_EXPECTED 157
+#define IDR_INVALID_BANNER 158
+#define IDR_INVALID_FORM_NAME 159
+#define IDR_INVALID_FORM_TYPE 160
+#define IDR_INVALID_LPT_NUMBER 161
+#define IDR_INVALID_PATH_NAME 162
+#define IDR_JOB_NOT_FOUND 163
+#define IDR_LPT_NUMBER_EXPECTED 164
+#define IDR_LPT_STATUS 165
+#define IDR_NOT_ACTIVE 166
+#define IDR_NO_AUTOENDCAP 167
+#define IDR_NO_PRINTERS 168
+#define IDR_LPT_STATUS_NO_BANNER 169
+#define IDR_QUEUE_NOT_EXIST 170
+#define IDR_SERVER_NOT_FOUND 171
+#define IDR_SUCCESS_QUEUE 172
+#define IDR_TABSIZE_OUTOF_RANGE 173
+#define IDR_TAB_SIZE_EXPECTED 174
+#define IDR_TIMEOUT_OUTOF_RANGE 175
+#define IDR_TIME_OUT_EXPECTED 176
+#define IDR_UNKNOW_FLAG 177
+#define IDR_DISABLED 178
+#define IDR_ENABLED 179
+#define IDR_YES 180
+#define IDR_NO 181
+#define IDR_SECONDS 182
+#define IDR_CONVERT_TO_SPACE 183
+#define IDR_NO_CONVERSION 184
+#define IDR_NOTIFY_USER 185
+#define IDR_NOT_NOTIFY_USER 186
+#define IDR_NONE 187
+#define IDR_CONNECTION_REFUSED 188
+#define IDR_LASTLOGIN_PM 189
+#define IDR_LASTLOGIN_AM 190
+#define IDR_ALL_LOCAL_DRIVES 191
+#define IDR_CHANGE_CONTEXT_ERROR 192
+#define IDR_GET_CONTEXT_ERROR 193
+#define IDR_DISPLAY_CONTEXT 194
+#define IDR_LPT_STATUS_NDS 195
+#define IDR_LPT_STATUS_NO_BANNER_NDS 196
+#define IDR_NO_QUEUE 197
+#define IDR_LASTLOGIN 198
+#define IDR_TREE_OPEN_FAILED 199
+#define IDR_NDS_CONTEXT_INVALID 200
+#define IDR_NDS_USERNAME_FAILED 201
+#define IDR_QUERY_INFO_FAILED 202
+#define IDR_NO_RESPONSE 203
+#define IDR_NDSQUEUE_NOT_EXIST 204
+#define IDR_NDSSUCCESS_QUEUE 205
+#define IDR_CAPTURE_FAILED 206
+#define IDR_CURRENT_TREE 207
+#define IDR_CURRENT_SERVER 208
+#define IDR_CURRENT_CONTEXT 209
+#define IDR_AUTHENTICATING_SERVER 210
+#define IDR_NO_END_QUOTE 211
diff --git a/private/nw/nwscript/lsparse.c b/private/nw/nwscript/lsparse.c
new file mode 100644
index 000000000..1b0e67fd1
--- /dev/null
+++ b/private/nw/nwscript/lsparse.c
@@ -0,0 +1,315 @@
+/*
+ * LSPARSE.C - NetWare Login Script processing routines for our Win32
+ * NetWare 3.x LOGIN clone.
+ *
+ * Based on code contained in NWPARSE.C, written by Xiao Ying Ding.
+ *
+ * Modified and re-written for Win32 by J. SOUZA, February 1994.
+ *
+ * Modified for NT by Terry Treder
+ *
+ * Copyright (C)1994 Microsoft Corporation.
+ *
+ */
+
+#include <common.h>
+
+/********************************************************************
+
+ ConverNDSPathToNetWarePathA
+
+Routine Description:
+
+ Convert a NDS path to a Netware format path
+
+Arguments:
+ ndspath - origninal NDS path
+ objclass - type of NDS object, NULL if unknown
+ nwpath - Netware format path
+
+Return Value:
+ error
+
+ *******************************************************************/
+unsigned int
+ConverNDSPathToNetWarePathA(char *ndspath, char *objclass, char *nwpath)
+{
+ CHAR szDN[MAX_PATH];
+ CHAR szObjName[MAX_PATH];
+ CHAR cSave;
+ CHAR className[MAX_PATH];
+
+ LPSTR lpDelim = NULL;
+ LPSTR lpFilePath = "";
+ LPSTR lpszValue;
+ LPSTR path;
+ LPSTR volume;
+
+ DWORD dwRet;
+ DWORD length;
+ UINT NWStatus;
+ char bufAttribute[2048];
+
+ // optimize for path beginning with drive letter
+ // This assumes NDS volume and dir map names are at least 2 chars
+
+ if (ndspath[1] == ':')
+ return 1;
+ // strip ':' from path before this call
+ if ( ( lpDelim = strchr(ndspath,':') ) != NULL
+ || ((lpDelim = strchr(ndspath,'\\')) != NULL)) {
+ cSave = *lpDelim;
+ *lpDelim = '\0';
+ lpFilePath = lpDelim+1;
+ }
+
+ if ( objclass == NULL ) {
+
+ NWStatus = NDSCanonicalizeName( ndspath, szObjName, MAX_PATH, TRUE );
+
+ if ( NWStatus != 0 ) {
+#ifdef DEBUG
+ printf("can't canonicalize [%s] (0x%x)\n",
+ ndspath, NWStatus );
+#endif
+
+ if (lpDelim) {
+ *lpDelim = cSave;
+ }
+
+ return 1;
+ }
+
+
+ NWStatus = NDSGetClassName( szObjName, className );
+
+ if ( NWStatus != 0 ||
+ strcmp ( className, DSCL_SERVER ) &&
+ strcmp ( className, DSCL_NCP_SERVER ) &&
+ strcmp ( className, DSCL_VOLUME ) &&
+ strcmp ( className, DSCL_QUEUE ) &&
+ strcmp ( className, DSCL_DIRECTORY_MAP )) {
+
+#ifdef DEBUG
+ printf("no path DSOBJ: %d (%s) (%s)\n",
+ NWStatus, szObjName, className );
+#endif
+
+ if (lpDelim) {
+ *lpDelim = cSave;
+ }
+
+ return 1;
+ }
+
+ objclass = className;
+ }
+ else
+ strcpy ( szObjName, ndspath );
+
+ if (lpDelim) {
+ *lpDelim = cSave;
+ }
+
+#ifdef DEBUG
+ printf("ConvertNDSPath BEFORE [%s]\n", szObjName);
+#endif
+
+ //
+ // Is f this is the server class object , we only need
+ // to extract it's common name and put into netware format
+ //
+ if ((strcmp(objclass,DSCL_SERVER) == 0 ) ||
+ (strcmp(objclass,DSCL_NCP_SERVER) == 0 )) {
+
+ // Abbreaviate first to remove type qualifiers
+ *szDN = '\0';
+ if (0 != NDSAbbreviateName(FLAGS_LOCAL_CONTEXT,(LPSTR)szObjName,szDN)) {
+ return 1;
+ }
+
+ // BUGBUG THis code should be separated as tokenizing function
+ lpDelim = strchr(szDN,'.');
+ if (lpDelim) {
+ *lpDelim = '\0';
+ }
+
+ strcpy(nwpath,szDN);
+
+#ifdef DEBUG
+ printf("Returning Netware path:%s\n",nwpath);
+#endif
+
+ return 0;
+
+ } /* endif server class */
+
+ //
+ // If this is share class object ( volume or queue), we need
+ // to find it's host server name and host resource name
+ //
+ if ((strcmp(objclass,DSCL_VOLUME) == 0 ) ||
+ (strcmp(objclass,DSCL_QUEUE) == 0 )
+ ) {
+
+ //
+ // Read host server name first. It comes back as distinguished
+ // directory name, so we will need to extract server name from it
+ //
+
+ NWStatus = NDSGetProperty ( szObjName,
+ DSAT_HOST_SERVER,
+ bufAttribute,
+ sizeof(bufAttribute),
+ NULL );
+
+ if (NWStatus != 0) {
+#ifdef DEBUG
+ printf("Get host server failed. err=0x%x\n",NWStatus);
+#endif
+ return 1;
+ }
+
+ lpszValue = bufAttribute;
+ ConvertUnicodeToAscii( lpszValue );
+
+ //
+ // Now copy server distinguished name into temporary buffer
+ // and call ourselves to convert it to Netware
+ //
+ strcpy(szDN,lpszValue);
+
+ dwRet = ConverNDSPathToNetWarePathA(szDN, DSCL_SERVER, nwpath);
+ if (dwRet) {
+#ifdef DEBUG
+ printf("Resolving server DN failed\n");
+#endif
+ //Break();
+ return 1;
+ }
+
+ //
+ // Get volume name itself
+ //
+ NWStatus = NDSGetProperty ( szObjName,
+ DSAT_HOST_RESOURCE_NAME,
+ bufAttribute,
+ sizeof(bufAttribute),
+ NULL );
+
+ if (NWStatus != 0) {
+#ifdef DEBUG
+ printf("Get host resource name failed. err=0x%x\n",NWStatus);
+#endif
+ return 1;
+ }
+
+ lpszValue = bufAttribute;
+ ConvertUnicodeToAscii( lpszValue );
+
+ //
+ // Now we already have server name in the user buffer,
+ // append share name to it
+ strcat(nwpath,"/");
+ strcat(nwpath,lpszValue);
+ strcat(nwpath,":");
+ strcat(nwpath, lpFilePath );
+
+#ifdef DEBUG
+ printf("Returning Netware path:%s\n",nwpath);
+#endif
+
+ return 0;
+
+ } /* endif Volume class */
+
+ //
+ // For directory maps we need to find host volume NDS name and
+ // append relative directory path
+ //
+ if (strcmp(objclass,DSCL_DIRECTORY_MAP) == 0 ) {
+
+ //
+ // First get NDS name for host volume object
+ //
+
+ NWStatus = NDSGetProperty ( szObjName,
+ DSAT_PATH,
+ bufAttribute,
+ sizeof(bufAttribute),
+ NULL );
+
+ if (NWStatus != 0) {
+#ifdef DEBUG
+ printf("Get path %s failed. err=0x%x\n", szObjName, NWStatus);
+#endif
+ return 1;
+ }
+
+ volume = bufAttribute;
+ volume += sizeof(DWORD);
+ volume += sizeof(DWORD);
+ ConvertUnicodeToAscii( volume );
+
+ // Path is next
+
+ path = bufAttribute;
+ path += sizeof(DWORD);
+ length = ROUNDUP4(*(DWORD *)path);
+ path += sizeof(DWORD);
+ path += length;
+
+ //
+ // Check for 0 length paths
+ //
+ if ( *(DWORD *)path == 0 ) {
+ path = "";
+ }
+ else {
+ path += sizeof(DWORD);
+ ConvertUnicodeToAscii( path );
+ }
+
+#ifdef DEBUG
+ printf("path is %s\n",path);
+#endif
+
+ //
+ // Now copy volume distinguished name into temporary buffer
+ // and call ourselves to convert it to NetWare
+ //
+ strcpy(szDN,volume);
+
+ dwRet = ConverNDSPathToNetWarePathA(szDN, DSCL_VOLUME, nwpath);
+ if (dwRet) {
+#ifdef DEBUG
+ printf("Resolving volume DN failed\n");
+#endif
+ //Break();
+ return 1;
+ }
+
+ //
+ // Now we already have NetWare server\volume name in the user buffer,
+ // append directory path to it
+ //strcat(nwpath,"\\");
+ // we want only one '\'
+ if (path[0] == '\\' || path[0] == '/') path++;
+ strcat(nwpath,path);
+ // append non-NDS part of path, if any
+ if (*lpFilePath) {
+ strcat(nwpath,"/");
+ strcat(nwpath, lpFilePath );
+ }
+
+#ifdef DEBUG
+ printf("Returning NetWare path:%s\n",nwpath);
+#endif
+
+ return 0;
+
+ } /* endif DirectoryMap class */
+
+ return(1);
+}
+
diff --git a/private/nw/nwscript/makefile b/private/nw/nwscript/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/nw/nwscript/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/nw/nwscript/maplist.c b/private/nw/nwscript/maplist.c
new file mode 100644
index 000000000..5dbe8a132
--- /dev/null
+++ b/private/nw/nwscript/maplist.c
@@ -0,0 +1,252 @@
+
+/*************************************************************************
+*
+* QATTACH.C
+*
+* Do any neccessary attach user queries
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\MAPLIST.C $
+*
+* Rev 1.1 10 Apr 1996 14:22:42 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.1 12 Mar 1996 19:53:58 terryt
+* Relative NDS names and merge
+*
+* Rev 1.0 22 Jan 1996 16:49:24 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include "common.h"
+
+//
+// 4X login script behavior for map commands to servers not in the
+// logged in NDS tree that have not been ATTACH'ed is different from
+// the 3X behavior.
+//
+// The 4X behavior is to always ask for a user name and password for
+// these servers, doing the attach at that point. The user gets
+// two trys.
+//
+// Since NT doesn't have an list of attached servers, and will try
+// to connect to a volume with the default user name and password,
+// a wrapper must be put around the MAP commands. This code
+// must determine that a bindery connection will be made and that
+// this server has not previously been MAP'ed or ATTACH'ed.
+// The user will be always prompted for user name and password.
+// The server will then be logged into with those credentials.
+//
+// One problem with the below is that it's not easy to tell that
+// a connection "will be" made with the bindery, this is done in
+// the redirector. So to simplify things the assumption is that
+// only 3X servers use bindery connections. This means that
+// 4X servers using bindery emulation on a different NDS tree will
+// not always be asked for the user name and password.
+//
+// Already processed servers are kept in a list and marked as 4X or 3X
+// for possible future use.
+//
+// The behavior for a 3X login depends on the LOGIN.EXE version.
+// The old behavior is that you must always ATTACH before mapping.
+// However, if you login to a 3X server with a 4X version LOGIN.EXE
+// it will try to authenticate using your user name (and password)
+// on the first attempt and ask for a password if that fails. The
+// second attempt will ask for your user name. Since this 4X behavior
+// is more forgiving (more scripts "work") that is the one being
+// emulated.
+//
+
+typedef struct _SERVERLIST
+{
+ char * ServerName;
+ unsigned int ServerType;
+ struct _SERVERLIST *pNextServer;
+} SERVERLIST, *PSERVERLIST;
+
+PSERVERLIST pMainList = NULL;
+
+BOOL IsServerInAttachList( char *, unsigned int );
+void AddServerToAttachList( char *, unsigned int );
+int DoAttachProcessing( char * );
+
+/*
+ * Scan the list for the server
+ */
+BOOL
+IsServerInAttachList( char * Server, unsigned int ServerType )
+{
+ PSERVERLIST pServerList = pMainList;
+
+ while ( pServerList != NULL )
+ {
+ if ( !_strcmpi( Server, pServerList->ServerName ) &&
+ ( ServerType & pServerList->ServerType ) )
+ return TRUE;
+ pServerList = pServerList->pNextServer;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Add the server to the list of attached servers
+ *
+ * This is used during MAP's and ATTACH's
+ */
+void
+AddServerToAttachList( char * Server, unsigned int ServerType )
+{
+ PSERVERLIST pServerList;
+
+ pServerList = (PSERVERLIST) malloc( sizeof( SERVERLIST ) );
+
+ if ( pServerList == NULL )
+ {
+ DisplayMessage( IDR_NOT_ENOUGH_MEMORY );
+ return;
+ }
+
+ pServerList->ServerName = _strdup( Server );
+ pServerList->ServerType = ServerType;
+ pServerList->pNextServer = pMainList;
+ pMainList = pServerList;
+}
+
+/*
+ * Do any Attach processing
+ * Return error code. 0 is success.
+ * 880F is the special "attached failed" error
+ */
+
+int
+DoAttachProcessing( char * PossibleServer )
+{
+ unsigned int iRet = 0;
+ unsigned int conn;
+ char userName[MAX_NAME_LEN] = "";
+ char password[MAX_PASSWORD_LEN] = "";
+ BOOL AlreadyConnected = FALSE;
+
+ //
+ // Must have a server to process
+ //
+ if ( !*PossibleServer )
+ return iRet;
+
+ // See if this server has been processed before
+ // No since in doing a 4X server twice, and you only ask
+ // for the user name and password once.
+
+ if ( IsServerInAttachList( PossibleServer,
+ LIST_4X_SERVER | LIST_3X_SERVER ) )
+ return iRet;
+
+ // See if there is already a connection to the server
+
+ if ( NTIsConnected( PossibleServer ) )
+ AlreadyConnected = TRUE;
+ else
+ AlreadyConnected = FALSE;
+
+ // Try and attach to the server
+
+ iRet = NTAttachToFileServer( PossibleServer, &conn );
+
+ // If attach failed, return
+
+ if ( iRet )
+ return iRet;
+
+ // If this is a 4X server then add it to the list of attached
+ // servers. We don't want to do this again. 4X servers must
+ // use the NDS attachment anyway (or at least I don't see a
+ // way of telling that it's going to be a bindery emulation
+ // connection ahead of time).
+
+ if ( fNDS && Is40Server( conn ) )
+ {
+ AddServerToAttachList( PossibleServer, LIST_4X_SERVER );
+ DetachFromFileServer ( conn );
+ return iRet;
+ }
+
+ // Close that first connection
+
+ DetachFromFileServer ( conn );
+
+ // If we are already connected, don't mess with things
+ // The credentials can't be changed anyway
+
+ if ( AlreadyConnected )
+ {
+ AddServerToAttachList( PossibleServer, LIST_3X_SERVER );
+ return iRet;
+ }
+
+ // Ask for user name on an NDS login
+ //
+ // Use the current login name for a 3X login on the first attempt
+
+ if ( fNDS )
+ {
+ DisplayMessage(IDR_ENTER_LOGIN_NAME, PossibleServer);
+ if (!ReadName(userName))
+ return 0x880F;
+ }
+ else
+ {
+ strncpy( userName, LOGIN_NAME, sizeof( userName ) );
+ }
+
+ // Try to log the user in, asking for a password
+
+ iRet = Login( userName,
+ PossibleServer,
+ password,
+ TRUE );
+
+ // Clear out the password
+ // We don't need it again
+
+ memset( password, 0, sizeof( password ) );
+
+ // If failed, give the user one more chance
+
+ if ( iRet )
+ {
+ // Ask for user name
+
+ DisplayMessage(IDR_ENTER_LOGIN_NAME, PossibleServer);
+ if (!ReadName(userName))
+ return 0x880F;
+
+ // Try to log the user in
+
+ iRet = Login( userName,
+ PossibleServer,
+ password,
+ TRUE );
+
+ // Clear out the password
+
+ memset( password, 0, sizeof( password ) );
+
+ }
+
+ // Add servername to list of attached servers, marked as 3X
+
+ if ( !iRet )
+ {
+ AddServerToAttachList( PossibleServer, LIST_3X_SERVER );
+ }
+ else
+ {
+ iRet = 0x880F; // Special I am not attached error
+ }
+
+ return iRet;
+
+}
+
diff --git a/private/nw/nwscript/ncp.c b/private/nw/nwscript/ncp.c
new file mode 100644
index 000000000..72b453350
--- /dev/null
+++ b/private/nw/nwscript/ncp.c
@@ -0,0 +1,356 @@
+
+/*************************************************************************
+*
+* NCP.C
+*
+* All routines doing direct NCPs or filecontrol operations
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NCP.C $
+*
+* Rev 1.2 10 Apr 1996 14:22:50 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:54:06 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:24:56 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:07:10 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <nwapi32.h>
+#include <ntddnwfs.h>
+
+#include "nwscript.h"
+#include "ntnw.h"
+#include "inc/nwlibs.h"
+
+
+/********************************************************************
+
+ NTGetUserID
+
+Routine Description:
+
+ Given a connection handle, return the user ID
+
+Arguments:
+
+ ConnectionHandle - Connection Handle
+ UserID - returned User ID
+
+Return Value:
+ 0 = success
+ else NT error
+
+ *******************************************************************/
+unsigned int
+NTGetUserID(
+ unsigned int ConnectionHandle,
+ unsigned long *pUserID
+ )
+{
+ NTSTATUS NtStatus ;
+ unsigned int ObjectType;
+ unsigned char LoginTime[7];
+ unsigned char UserName[48];
+ VERSION_INFO VerInfo;
+ unsigned int Version;
+ unsigned int ConnectionNum;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)ConnectionHandle ;
+
+ NtStatus = GetConnectionNumber( ConnectionHandle, &ConnectionNum );
+
+ if (!NT_SUCCESS(NtStatus))
+ return NtStatus;
+
+ NtStatus = NWGetFileServerVersionInfo( (NWCONN_HANDLE)ConnectionHandle,
+ &VerInfo );
+
+ if (!NT_SUCCESS(NtStatus))
+ return NtStatus;
+
+ Version = VerInfo.Version * 1000 + VerInfo.SubVersion * 10;
+
+ if ( ( Version >= 3110 ) || ( Version < 2000 ) ) {
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 8, // Max request packet size
+ 63, // Max response packet size
+ "br|rrrr", // Format string
+ // === REQUEST ================================
+ 0x1c, // b Get Connection Information
+ &ConnectionNum, 4, // r Connection Number
+ // === REPLY ==================================
+ pUserID, 4, // r Object ID
+ &ObjectType, 2, // r Object Type
+ UserName, 48, // r UserName
+ LoginTime, 7 // r Login Time
+ );
+ }
+ else {
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 4, // Max request packet size
+ 63, // Max response packet size
+ "bb|rrrr", // Format string
+ // === REQUEST ================================
+ 0x16, // b Get Connection Information
+ ConnectionNum, // b Connection Number
+ // === REPLY ==================================
+ pUserID, 4, // r Object ID
+ &ObjectType, 2, // r Object Type
+ UserName, 48, // r UserName
+ LoginTime, 7 // r Login Time
+ );
+ }
+
+ return NtStatus;
+}
+
+/********************************************************************
+
+ GetConnectionNumber
+
+Routine Description:
+
+ Given a ConnectionHandle, return the NetWare Connection number
+
+Arguments:
+
+ ConnectionHandle - Connection Handle
+ pConnectionNumber - pointer to returned connection number
+
+Return Value:
+ 0 = success
+ else NT error
+
+ *******************************************************************/
+unsigned int
+GetConnectionNumber(
+ unsigned int ConnectionHandle,
+ unsigned int * pConnectionNumber )
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ NWR_GET_CONNECTION_DETAILS Details;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)ConnectionHandle ;
+
+ Status = NtFsControlFile(
+ pServerInfo->hConn, // Connection Handle
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_GET_CONN_DETAILS,
+ NULL,
+ 0,
+ (PVOID) &Details,
+ sizeof(Details));
+
+ if (Status == STATUS_SUCCESS) {
+ Status = IoStatusBlock.Status;
+ }
+
+ if (NT_SUCCESS(Status)) {
+ *pConnectionNumber = 256 * Details.ConnectionNumberHi +
+ Details.ConnectionNumberLo;
+ }
+
+ return Status;
+}
+
+/********************************************************************
+
+ GetInternetAddress
+
+Routine Description:
+
+ Return the address of the current system
+
+Arguments:
+
+ ConnectionHandle - Connection Handle
+ ConnectionNum - Connection Number
+ pAddress - returned address
+
+Return Value:
+ 0 = success
+ else NT error
+
+ *******************************************************************/
+unsigned int
+GetInternetAddress(
+ unsigned int ConnectionHandle,
+ unsigned int ConnectionNum,
+ unsigned char *pAddress
+ )
+{
+ NTSTATUS NtStatus ;
+ VERSION_INFO VerInfo;
+ unsigned int Version;
+ unsigned char Address[12];
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)ConnectionHandle ;
+
+ NtStatus = NWGetFileServerVersionInfo( (NWCONN_HANDLE)ConnectionHandle,
+ &VerInfo );
+
+ if (!NT_SUCCESS(NtStatus))
+ return NtStatus;
+
+ Version = VerInfo.Version * 1000 + VerInfo.SubVersion * 10;
+
+ if ( ( Version >= 3110 ) || ( Version < 2000 ) ) {
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 7, // Max request packet size
+ 14, // Max response packet size
+ "br|r", // Format string
+ // === REQUEST ================================
+ 0x1a, // b Get Connection Information
+ &ConnectionNum, 4, // r Connection Number
+ // === REPLY ==================================
+ Address, 12 // r Login Time
+ );
+ }
+ else {
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Bindery function
+ 4, // Max request packet size
+ 14, // Max response packet size
+ "bb|r", // Format string
+ // === REQUEST ================================
+ 0x13, // b Get Connection Information
+ (unsigned char)ConnectionNum, // b Connection Number
+ // === REPLY ==================================
+ Address, 12 // r Login Time
+ );
+ }
+ memcpy( pAddress, Address, 10 );
+
+ return NtStatus;
+}
+
+
+/********************************************************************
+
+ GetBinderyObjectID
+
+Routine Description:
+
+ Get the object ID of a named object in the bindery
+
+Arguments:
+
+ ConnectionHandle - Server connection handle
+ pObjectName - Name of object
+ ObjectType - Object type
+ pObjectId - returned object ID
+
+
+Return Value:
+ 0 = success
+ else NT error
+
+ *******************************************************************/
+unsigned int
+GetBinderyObjectID(
+ unsigned int ConnectionHandle,
+ char *pObjectName,
+ unsigned short ObjectType,
+ unsigned long *pObjectId )
+{
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)ConnectionHandle ;
+ unsigned int reply;
+
+ reply = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ FSCTL_NWR_NCP_E3H, // Directory function
+ 54, // Max request packet size
+ 56, // Max response packet size
+ "brp|r", // Format string
+ // === REQUEST ================================
+ 0x35, // b Get object ID
+ &ObjectType, W_SIZE, // r Object type HI-LO
+ pObjectName, // p UserName
+ // === REPLY ==================================
+ pObjectId, 4 // 4 bytes of raw data
+ );
+ return reply;
+}
+
+/********************************************************************
+
+ GetDefaultPrinterQueue
+
+Routine Description:
+
+ Get the default printer queue.
+
+Arguments:
+ ConnectionHandle - IN
+ Handle to server
+ pServerName - IN
+ File server name
+ pQueueName - OUT
+ Default printer queue name
+
+
+Return Value:
+
+ *******************************************************************/
+unsigned int
+GetDefaultPrinterQueue (
+ unsigned int ConnectionHandle,
+ unsigned char *pServerName,
+ unsigned char *pQueueName
+ )
+{
+ unsigned long ObjectID;
+ NTSTATUS NtStatus ;
+ PNWC_SERVER_INFO pServerInfo = (PNWC_SERVER_INFO)ConnectionHandle ;
+ NWOBJ_TYPE ObjectType;
+ NWCCODE Nwcode;
+
+ NtStatus = NwlibMakeNcp(
+ pServerInfo->hConn, // Connection Handle
+ NWR_ANY_F2_NCP(0x11), // F2 Function function
+ 4, // Max request packet size
+ 4, // Max response packet size
+ "wbb|d", // Format string
+ // === REQUEST ================================
+ 0x2, // w Length
+ 0xA, // b Subfunction
+ 0, // b printer number
+ // === REPLY ==================================
+ &ObjectID // d Object ID of Queue
+ );
+
+ if ( !NT_SUCCESS( NtStatus ) )
+ return ( NtStatus & 0xFF );
+
+ Nwcode = NWGetObjectName( (NWCONN_HANDLE) ConnectionHandle,
+ ObjectID,
+ pQueueName,
+ &ObjectType );
+
+ return Nwcode;
+}
diff --git a/private/nw/nwscript/nds.c b/private/nw/nwscript/nds.c
new file mode 100644
index 000000000..1b73643f5
--- /dev/null
+++ b/private/nw/nwscript/nds.c
@@ -0,0 +1,1505 @@
+/*************************************************************************
+*
+* NDS.C
+*
+* NT NetWare NDS routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+*************************************************************************/
+#include <common.h>
+
+DWORD GUserObjectID;
+HANDLE GhRdr;
+
+
+WCHAR * NDSTREE_w = NULL;
+UNICODE_STRING NDSTREE_u;
+
+/********************************************************************
+
+ ExpandRelativeName
+
+Routine Description:
+
+ If the name is a relative NDS name append the proper context
+ to the end. A relative name has periods on the end. Each
+ period represents one level up the NDS tree.
+
+Arguments:
+
+Return Value:
+
+ *******************************************************************/
+void
+ExpandRelativeName( LPSTR RelativeName, LPSTR AbsoluteName, unsigned int Len,
+ LPSTR Context )
+{
+
+ PBYTE ptr;
+ unsigned int i;
+ unsigned int count = 0;
+
+ strncpy( AbsoluteName, RelativeName, Len );
+
+ if ( ( AbsoluteName[0] == '.' ) &&
+ ( AbsoluteName[ strlen( AbsoluteName ) - 1 ] != '.' ) )
+ return;
+
+ if ( ( strlen( AbsoluteName ) + strlen( Context ) ) > Len )
+ {
+ DisplayMessage( IDR_NOT_ENOUGH_MEMORY );
+ return;
+ }
+
+ if ( AbsoluteName[0] == '\0' )
+ {
+ return;
+ }
+
+ ptr = &AbsoluteName[ strlen( AbsoluteName ) - 1 ];
+
+ // Count the number of periods and back up over them.
+
+ if ( *ptr != '.' )
+ {
+ //
+ // No periods at the end
+ // Assume this is a relative name and append the context
+ //
+ strcat( AbsoluteName, "." );
+ strcat( AbsoluteName + strlen( AbsoluteName ), Context );
+ return;
+ }
+
+ while ( *ptr == '.' )
+ {
+ ptr--;
+ count++;
+ }
+
+ ptr++;
+ *ptr = '\0';
+
+ // ptr now points to where the copy of the rest of the context should start
+ // skip the first "count" entries in the context
+
+ ptr = Context;
+
+ for ( i = 0; i < count; i++ )
+ {
+ ptr = strchr( ptr, '.' );
+ if ( ptr == NULL )
+ {
+ return;
+ }
+ ptr++;
+ }
+ ptr--;
+
+ // Now append
+
+ strcat( AbsoluteName, ptr );
+
+}
+
+
+
+/********************************************************************
+
+ NDSGetNameContext
+
+Routine Description:
+
+ Get the current context
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+NTSTATUS
+NDSGetNameContext( LPSTR Context, BOOLEAN flag )
+{
+ //
+ // For NdsResolveName.
+ //
+
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ HANDLE hReferredServer;
+ DWORD dwHandleType;
+
+ NTSTATUS Status;
+
+ OEM_STRING oemStr;
+ UNICODE_STRING defaultcontext;
+ DWORD ThisObjectID;
+ BYTE Buffer[2048];
+ WCHAR NdsStr[1024];
+ PBYTE ptr;
+
+ defaultcontext.Length = 0;
+ defaultcontext.MaximumLength = sizeof( NdsStr );
+ defaultcontext.Buffer = NdsStr;
+
+ Status = NwNdsGetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( GhRdr,
+ &defaultcontext,
+ &ThisObjectID,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // should change the global handle.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_NDS_USERNAME_FAILED);
+ return Status;
+ }
+
+ CloseHandle( GhRdr );
+ GhRdr = hReferredServer;
+ }
+
+ Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO );
+ ptr += ROUNDUP4(*(DWORD *)ptr);
+ ptr += sizeof(DWORD);
+ ptr += sizeof(DWORD);
+
+ defaultcontext.Length = wcslen( (WCHAR *)ptr ) * 2;
+ defaultcontext.MaximumLength = defaultcontext.Length;
+ defaultcontext.Buffer = (WCHAR *)ptr;
+
+ oemStr.Length = 0;
+ oemStr.MaximumLength = NDS_NAME_CHARS;
+ oemStr.Buffer = Context;
+
+ RtlUnicodeStringToOemString( &oemStr, &defaultcontext, FALSE );
+
+ return 0;
+}
+
+/********************************************************************
+
+ NDSTypeless
+
+Routine Description:
+
+ Change name to typelese
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+unsigned int
+NDSTypeless( LPSTR OrigName , LPSTR TypelessName )
+{
+ int i,j;
+ PBYTE p;
+
+ i = 0;
+ j = 0;
+
+ if ( !_strnicmp( "CN=", OrigName, 3 ) ||
+ !_strnicmp( "OU=", OrigName, 3 ) )
+ {
+ i += 3;
+ }
+ else if ( !_strnicmp( "C=", OrigName, 2 ) ||
+ !_strnicmp( "O=", OrigName, 2 ) )
+ {
+ i += 2;
+ }
+
+ for ( ; (( i < NDS_NAME_CHARS ) && ( OrigName[i] ) ); i++ )
+ {
+ if ( !_strnicmp( ".CN=", &OrigName[i], 4 ) ||
+ !_strnicmp( ".OU=", &OrigName[i], 4 ) )
+ {
+ TypelessName[j++]= '.';
+ i += 3;
+ continue;
+ }
+ if ( !_strnicmp( ".C=", &OrigName[i], 3 ) ||
+ !_strnicmp( ".O=", &OrigName[i], 3 ) )
+ {
+ TypelessName[j++]= '.';
+ i += 2;
+ continue;
+ }
+ /*
+ * Strip out multiple blanks
+ */
+ if ( !_strnicmp( " ", &OrigName[i], 2 ) )
+ {
+ continue;
+ }
+ TypelessName[j++] = OrigName[i];
+ }
+
+ TypelessName[j] = '\0';
+
+ return 0;
+}
+
+/********************************************************************
+
+ NDSAbbreviateName
+
+Routine Description:
+
+ Abbreviate name
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+unsigned int
+NDSAbbreviateName( DWORD Flags, LPSTR OrigName , LPSTR AbbrevName )
+{
+ BYTE Buffer[NDS_NAME_CHARS];
+ BYTE CurrentContext[NDS_NAME_CHARS];
+ PBYTE p;
+ PBYTE c;
+ NTSTATUS Status;
+
+ if ( OrigName[0] == '.' )
+ NDSTypeless( OrigName + 1, Buffer );
+ else
+ NDSTypeless( OrigName, Buffer );
+
+ /*
+ * We want a relative name
+ */
+ if ( Flags & FLAGS_LOCAL_CONTEXT )
+ {
+ p = &Buffer[strlen(Buffer)-strlen(REQUESTER_CONTEXT)];
+ if ( !_strcmpi( REQUESTER_CONTEXT, p ) )
+ {
+ // The name is below us
+
+ if ( ( *(p-1) == '.' ) && ( p > Buffer ) )
+ p--;
+ *p = '\0';
+ strcpy( AbbrevName, Buffer );
+ }
+ else
+ {
+ //
+ // Going from back to front for each section of context
+ // in common with AbbrevName
+ // truncate both
+ // Going from back to front for each section of context
+ // left over
+ // concatonate a period to AbbrevName
+ //
+ // Example
+ //
+ // Name: w.x.y.z Context: a.b.z => w.x.y..
+ //
+
+ strcpy( CurrentContext, REQUESTER_CONTEXT );
+ strcpy( AbbrevName, Buffer );
+
+ if ( CurrentContext[0] && AbbrevName[0] )
+ {
+ c = &CurrentContext[ strlen( CurrentContext ) ] - 1;
+ p = &AbbrevName[ strlen( AbbrevName ) ] - 1;
+
+ //
+ // Strip off the matching names from end to front
+ //
+ for ( ;; )
+ {
+ if ( ( c == CurrentContext ) && ( *p == '.' ) )
+ {
+ *c = '\0';
+ *p = '\0';
+ break;
+ }
+
+ if ( *c != *p )
+ break;
+
+ if ( ( *c == '.' ) && ( *p == '.' ) )
+ {
+ *c = '\0';
+ *p = '\0';
+ }
+
+ if ( ( c == CurrentContext ) || ( p == AbbrevName ) )
+ {
+ break;
+ }
+
+ c--; p--;
+ }
+
+ //
+ // Count the remaining sections of the context and
+ // add that number of periods to the end of the buffer.
+ // That is how far we need to back up before getting
+ // to a matching branch of the tree.
+ //
+
+ if ( CurrentContext[0] ) {
+ strcat( AbbrevName, "." );
+ for ( c = CurrentContext; *c; c++ ) {
+ if ( *c == '.' )
+ strcat( AbbrevName, "." );
+ }
+ }
+ }
+
+ }
+ }
+ else
+ strcpy( AbbrevName, Buffer );
+
+ return 0;
+}
+
+
+/********************************************************************
+
+ NDSInitUserProperty
+
+Routine Description:
+
+ none
+
+Arguments:
+ none
+
+Return Value:
+ 0 = no error
+
+ *******************************************************************/
+unsigned int
+NDSInitUserProperty( )
+{
+ NTSTATUS Status;
+ UNICODE_STRING ObjectName;
+ PWCHAR lpT;
+ UNICODE_STRING defaultcontext;
+
+ //
+ // For NdsResolveName.
+ //
+
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ HANDLE hReferredServer;
+ DWORD dwHandleType;
+
+ //
+ // Get a handle to the redirector.
+ //
+
+ Status = NwNdsOpenTreeHandle( &NDSTREE_u, &GhRdr );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_TREE_OPEN_FAILED);
+ return 1;
+ }
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+
+ RtlInitUnicodeString( &ObjectName, TYPED_USER_NAME_w );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( GhRdr,
+ &ObjectName,
+ &GUserObjectID,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_NDS_USERNAME_FAILED);
+ return 1;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // should change the global handle.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_NDS_USERNAME_FAILED);
+ return 1;
+ }
+
+ CloseHandle( GhRdr );
+ GhRdr = hReferredServer;
+ }
+
+ //
+ // Set the current context to what we think it should be
+ // (At the user's location.)
+ //
+
+ lpT = wcschr( TYPED_USER_NAME_w, L'.' );
+ if ( lpT )
+ {
+ RtlInitUnicodeString( &defaultcontext, lpT+1 );
+ }
+ else
+ {
+ RtlInitUnicodeString( &defaultcontext, L"" );
+ }
+
+ Status = NwNdsSetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_NDS_CONTEXT_INVALID);
+ return 1;
+ }
+
+ return 0;
+
+
+}
+
+/********************************************************************
+
+ NDSCanonicalizeName
+
+Routine Description:
+
+ return a canonicalized version of a name
+
+Arguments:
+ Name - original name
+ CanonName - Canonicalized name
+ Len - length of CanonName
+ fCurrentContext - TRUE => use current contex, FALSE use
+ requester context
+
+Return Value:
+ status error
+
+ *******************************************************************/
+unsigned int
+NDSCanonicalizeName( PBYTE Name, PBYTE CanonName, int Len, int fCurrentContext )
+{
+ NTSTATUS Status;
+ int ccode = -1;
+ DWORD ThisObjectID;
+ OEM_STRING oemStr;
+ UNICODE_STRING ObjectName;
+ BYTE Buffer[2048];
+ BYTE FullName[NDS_NAME_CHARS];
+ PBYTE ptr;
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ DWORD dwHandleType;
+ HANDLE hReferredServer;
+ unsigned char CurrentContext[NDS_NAME_CHARS];
+
+ //
+ // Cope with relative names
+ //
+ if ( fCurrentContext )
+ {
+ Status = NDSGetNameContext( CurrentContext, TRUE );
+ if ( !NT_SUCCESS( Status ) )
+ return Status;
+ ExpandRelativeName( Name, FullName, NDS_NAME_CHARS, CurrentContext );
+ }
+ else
+ ExpandRelativeName( Name, FullName, NDS_NAME_CHARS, REQUESTER_CONTEXT );
+
+ //
+ // Fill it in in case we have an error
+ //
+ strncpy( CanonName, FullName, Len);
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+ // Unfortuneately, the name resolver doesn't understand periods at the
+ // front or end (absolute or relative names)
+ //
+
+ if ( FullName[0] == '.' )
+ {
+ oemStr.Length = strlen( FullName + 1 );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = FullName + 1;
+ }
+ else
+ {
+ oemStr.Length = strlen( FullName );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = FullName;
+ }
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(Buffer);
+ ObjectName.Buffer = (WCHAR *)Buffer;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( GhRdr,
+ &ObjectName,
+ &ThisObjectID,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // should change the global handle.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ CloseHandle( GhRdr );
+ GhRdr = hReferredServer;
+ }
+
+ Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO );
+ ptr += ROUNDUP4(*(DWORD *)ptr);
+ ptr += sizeof(DWORD);
+ ptr += sizeof(DWORD);
+
+ RtlInitUnicodeString( &ObjectName, (PWCHAR)ptr );
+
+ oemStr.Length = 0;
+ oemStr.MaximumLength = Len;
+ oemStr.Buffer = CanonName;
+
+ RtlUnicodeStringToOemString( &oemStr, &ObjectName, FALSE );
+
+ return 0;
+}
+
+/********************************************************************
+
+ NDSGetUserProperty
+
+Routine Description:
+
+ Return the NDS property for the object
+
+Arguments:
+ Property - property name
+ Data - data buffer
+ Size - size of data buffer
+
+Return Value:
+ 0 no error
+
+ *******************************************************************/
+unsigned int
+NDSGetUserProperty( PBYTE Property,
+ PBYTE Data,
+ unsigned int Size,
+ SYNTAX * pSyntaxID,
+ unsigned int * pActualSize )
+{
+ NTSTATUS Status;
+ int ccode = -1;
+
+ OEM_STRING oemStr;
+ UNICODE_STRING PropertyName;
+ WCHAR NdsStr[1024];
+ DWORD iterhandle = INITIAL_ITERATION;
+
+ BYTE Buffer[2048];
+ DWORD BufferSize = 2048;
+ PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
+ PNDS_ATTRIBUTE pAttribute;
+ PBYTE pAttribValue;
+
+ //
+ // Read the User property
+ //
+
+ memset(Buffer, 0, BufferSize);
+
+ oemStr.Length = strlen( Property );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Property;
+
+ PropertyName.Length = 0;
+ PropertyName.MaximumLength = sizeof(NdsStr);
+ PropertyName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &PropertyName, &oemStr, FALSE );
+
+ Status = NwNdsReadAttribute ( GhRdr,
+ GUserObjectID,
+ &iterhandle,
+ &PropertyName,
+ Buffer,
+ BufferSize );
+
+ if ( NT_SUCCESS(Status) )
+ {
+ int i;
+ pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)Buffer;
+ pAttribute = (PNDS_ATTRIBUTE)(Buffer
+ + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
+ if ( pSyntaxID )
+ {
+ *pSyntaxID = pAttribute->SyntaxID;
+ }
+
+ pAttribValue = (PBYTE)(pAttribute->AttribName) +
+ ROUNDUP4(pAttribute->AttribNameLength) +
+ sizeof(DWORD);
+
+ if ( pActualSize )
+ {
+ *pActualSize = *(DWORD *)pAttribValue;
+ }
+
+ memcpy( Data, pAttribValue + sizeof(DWORD),
+ min(*(DWORD *)pAttribValue, Size) );
+
+ }
+
+ return Status;
+}
+
+
+/********************************************************************
+
+ NDSGetVar
+
+Routine Description:
+
+ Return value of user property
+
+ Get the syntax type of the property
+ Retrieve the data
+ Do any data conversion
+
+Arguments:
+ Name - of NDS property IN
+ Value - value buffer OUT
+ Size - size of value buffer IN
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+NDSGetVar ( PBYTE Name, PBYTE Value, unsigned int Size)
+{
+ unsigned int err;
+ SYNTAX Syntax;
+ BYTE Buffer[ATTRBUFSIZE];
+ DWORD ActualSize;
+
+ Value[0] = 0;
+
+ err = NDSGetUserProperty( Name, Buffer, ATTRBUFSIZE, &Syntax, &ActualSize );
+
+ if ( err )
+ {
+ return;
+ }
+
+ switch ( Syntax )
+ {
+ case NDSI_BOOLEAN:
+ if ( *(PBYTE)Buffer )
+ {
+ strcpy( Value, "Y" );
+ }
+ else
+ {
+ strcpy( Value, "N" );
+ }
+ break;
+ case NDSI_DIST_NAME:
+ case NDSI_CE_STRING:
+ case NDSI_CI_STRING:
+ case NDSI_OCTET_STRING:
+ case NDSI_PR_STRING:
+ case NDSI_NU_STRING:
+ case NDSI_TEL_NUMBER:
+ case NDSI_CLASS_NAME:
+ ConvertUnicodeToAscii( Buffer );
+ if ( Syntax == NDSI_DIST_NAME )
+ NDSAbbreviateName(FLAGS_LOCAL_CONTEXT, Buffer, Buffer);
+ strncpy( Value, Buffer, Size );
+ break;
+ case NDSI_CI_LIST:
+ ConvertUnicodeToAscii( Buffer+8 );
+ strncpy( Value, Buffer+8, Size );
+ break;
+ break;
+ case NDSI_INTEGER:
+ case NDSI_COUNTER:
+ case NDSI_TIME:
+ case NDSI_INTERVAL:
+ case NDSI_TIMESTAMP:
+ sprintf( Value, "%d", *(int *)Buffer );
+ break;
+ case NDSI_PO_ADDRESS:
+ {
+ // 6 null terminated lines
+ int line,len;
+ PBYTE ptr = Buffer + 4;
+
+ // Stop if not 6 lines
+ if ( *(int *)Buffer != 6 )
+ break;
+
+ for (line = 0; line <= 5; line++) {
+ len = ROUNDUP4(*(int *)ptr);
+ ptr += 4;
+ if ( !len )
+ break;
+ ConvertUnicodeToAscii( ptr );
+ strcat( Value, ptr );
+ strcat( Value, "\n" );
+ ptr += len;
+ }
+ }
+ break;
+ case NDSI_FAX_NUMBER:
+ if ( *(int *)Buffer == 0 )
+ return;
+ ConvertUnicodeToAscii( Buffer+4 );
+ strncpy( Value, Buffer+4, Size );
+ break;
+ case NDSI_EMAIL_ADDRESS:
+ if ( *(int *)(Buffer+4) == 0 )
+ return;
+ ConvertUnicodeToAscii( Buffer+8 );
+ strncpy( Value, Buffer+8, Size );
+ break;
+ case NDSI_PATH:
+ {
+ int len;
+
+ len = *(int *)(Buffer+4);
+ if ( len == 0 )
+ break;
+ len = ROUNDUP4( len );
+ ConvertUnicodeToAscii( Buffer+8 );
+ strcpy( Value, Buffer+8 );
+ NDSAbbreviateName(FLAGS_LOCAL_CONTEXT, Value, Value);
+ strcat( Value, ":" );
+ if ( *(int *)(Buffer + 8 + len) == 0 )
+ break;
+ ConvertUnicodeToAscii( Buffer+8+len+4 );
+ strcat( Value, Buffer+8+len+4 );
+ break;
+ }
+ case NDSI_NET_ADDRESS:
+ case NDSI_OCTET_LIST:
+ case NDSI_OBJECT_ACL:
+ case NDSI_STREAM:
+ case NDSI_UNKNOWN:
+ case NDSI_REPLICA_POINTER:
+ case NDSI_BACK_LINK:
+ case NDSI_TYPED_NAME:
+ case NDSI_HOLD:
+ case NDSI_TAX_COUNT:
+ default:
+ Value[0] = '\0';
+ Value[1] = '\0';
+ break;
+ }
+
+}
+
+/********************************************************************
+
+ NDSChangeContext
+
+Routine Description:
+
+ Change the current context
+
+Arguments:
+ Context - context string IN
+
+Return Value:
+ error number
+
+ *******************************************************************/
+unsigned int
+NDSChangeContext( PBYTE Context )
+{
+ NTSTATUS Status;
+
+ OEM_STRING oemStr;
+ UNICODE_STRING defaultcontext;
+ WCHAR NdsStr[1024];
+
+ oemStr.Length = strlen( Context );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Context;
+
+ defaultcontext.Length = 0;
+ defaultcontext.MaximumLength = sizeof(NdsStr);
+ defaultcontext.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &defaultcontext, &oemStr, FALSE );
+
+ Status = NwNdsSetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
+
+ return Status;
+}
+
+/********************************************************************
+
+ NDSGetContext
+
+Routine Description:
+
+ Retrieve the current context
+
+Arguments:
+ Buffer - data buffer for context string OUT
+ len - length of data buffer IN
+
+Return Value:
+ error number
+
+ *******************************************************************/
+unsigned int
+NDSGetContext( PBYTE Buffer,
+ unsigned int len )
+{
+ NTSTATUS Status;
+
+ Status = NDSGetNameContext( Buffer, TRUE );
+ if ( !NT_SUCCESS( Status ) )
+ return Status;
+ NDSAbbreviateName(FLAGS_NO_CONTEXT, Buffer, Buffer);
+ return 0;
+}
+
+/********************************************************************
+
+ NDSfopenStream
+
+Routine Description:
+
+ Open a file handle to an NDS stream property
+
+Arguments:
+ Object - name of object IN
+ Property - name of property IN
+ pStream - pointer to file handle OUT
+ pFileSize - pointer to file size OUT
+
+Return Value:
+ error
+
+ *******************************************************************/
+unsigned int
+NDSfopenStream ( PBYTE Object,
+ PBYTE Property,
+ PHANDLE pStream,
+ unsigned int * pFileSize )
+{
+ //
+ // Status variables.
+ //
+
+ NTSTATUS Status;
+ int ccode = -1;
+
+ //
+ // For NwNdsOpenTreeHandle.
+ //
+
+ HANDLE hRdr;
+ OEM_STRING oemStr;
+ UNICODE_STRING ObjectName;
+ WCHAR NdsStr[1024];
+
+ //
+ // For NwNdsResolveName.
+ //
+
+ DWORD dwOid;
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ DWORD dwHandleType;
+ HANDLE hReferredServer;
+
+ //
+ // Get a handle to the redirector.
+ //
+
+ Status = NwNdsOpenTreeHandle( &NDSTREE_u, &hRdr );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_TREE_OPEN_FAILED);
+ return ccode;
+ }
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+
+ if ( !Object )
+ {
+ return 1;
+ }
+
+ oemStr.Length = strlen( Object );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Object;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(NdsStr);
+ ObjectName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( hRdr,
+ &ObjectName,
+ &dwOid,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // must jump to that server before continuing.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ CloseHandle( hRdr );
+ hRdr = hReferredServer;
+ }
+
+ //
+ // Open the file stream.
+ //
+
+ oemStr.Length = strlen( Property );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Property;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(NdsStr);
+ ObjectName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ //
+ // Try to open a file stream for read access.
+ //
+
+ Status = NwNdsOpenStream( hRdr,
+ dwOid,
+ &ObjectName,
+ 1, // Read access.
+ pFileSize );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ *pStream = hRdr;
+
+ return 0;
+}
+
+/*
+ * IsMemberOfNDSGroup
+ * ------------------
+ *
+ * Returns true if currently logged in user object is member of group with given name
+ *
+ */
+unsigned int
+IsMemberOfNDSGroup(
+ PBYTE nwGroup
+ )
+{
+ NTSTATUS Status;
+ UINT nwRet;
+ BYTE szCanonTargetGroupName[NDS_NAME_CHARS+1];
+ UINT syntaxid;
+ UINT actualsize;
+ LPSTR szBuffer;
+ LPSTR pProp;
+ UINT i;
+ DWORD iterhandle = INITIAL_ITERATION;
+ UINT fFoundGroup = FALSE;
+ PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
+ PNDS_ATTRIBUTE pAttribute;
+ PBYTE pAttribValue;
+ UNICODE_STRING PropertyName;
+ UINT numvalues = 0;
+
+
+ szBuffer = (BYTE *)malloc(ATTRBUFSIZE);
+
+ if ( !szBuffer ) {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ memset( szBuffer, 0, ATTRBUFSIZE );
+
+ // Canonicalize name according to current context
+
+ strcpy( szCanonTargetGroupName, nwGroup );
+
+ nwRet = NDSCanonicalizeName( szCanonTargetGroupName,
+ szCanonTargetGroupName,
+ NDS_NAME_CHARS,
+ TRUE );
+ if (nwRet) {
+
+ if ( nwGroup[0] != '.' ) {
+
+ // Try an absolute name
+
+ strcpy( szCanonTargetGroupName, "." );
+ strcat( szCanonTargetGroupName, nwGroup );
+
+ nwRet = NDSCanonicalizeName( szCanonTargetGroupName,
+ szCanonTargetGroupName,
+ NDS_NAME_CHARS,
+ TRUE );
+ }
+
+ if ( nwRet )
+ goto CleanRet;
+ }
+
+ // Should check class name of object
+
+ RtlInitUnicodeString( &PropertyName, L"Group Membership" );
+
+ Status = NwNdsReadAttribute ( GhRdr,
+ GUserObjectID,
+ &iterhandle,
+ &PropertyName,
+ szBuffer,
+ ATTRBUFSIZE );
+
+ if ( !NT_SUCCESS(Status) )
+ {
+ return FALSE;
+ }
+
+ pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)szBuffer;
+
+ pAttribute = (PNDS_ATTRIBUTE)(szBuffer
+ + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
+ pAttribute->SyntaxID;
+
+ pAttribValue = (PBYTE)(pAttribute->AttribName) +
+ ROUNDUP4(pAttribute->AttribNameLength) +
+ sizeof(DWORD);
+
+ numvalues = *(PUINT)((PBYTE)(pAttribute->AttribName) +
+ ROUNDUP4(pAttribute->AttribNameLength));
+
+ if ( *(DWORD *)pAttribValue == 0 )
+ {
+ return FALSE;
+ }
+
+ for ( i = 0; i < numvalues; i++ ) {
+ ConvertUnicodeToAscii( pAttribValue+sizeof(DWORD) );
+ if (!_stricmp(pAttribValue+sizeof(DWORD),szCanonTargetGroupName)) {
+ fFoundGroup = TRUE;
+ break;
+ }
+ pAttribValue += ROUNDUP4(*(PUINT)pAttribValue) + sizeof(DWORD);
+ }
+
+
+
+CleanRet:
+ if (szBuffer ) {
+ free (szBuffer);
+ }
+ return fFoundGroup;
+}
+
+/********************************************************************
+
+ NDSGetProperty
+
+Routine Description:
+
+ Return the NDS property for the object
+
+Arguments:
+ Object - name of object IN
+ Property - property name IN
+ Data - data buffer OUT
+ Size - size of data buffer IN
+ pActualSize - real data size OUT
+
+Return Value:
+ error
+
+ *******************************************************************/
+unsigned int
+NDSGetProperty ( PBYTE Object,
+ PBYTE Property,
+ PBYTE Data,
+ unsigned int Size,
+ unsigned int * pActualSize )
+{
+ //
+ // Status variables.
+ //
+
+ NTSTATUS Status;
+ int ccode = -1;
+
+ //
+ // For NwNdsOpenTreeHandle.
+ //
+
+ HANDLE hRdr;
+ OEM_STRING oemStr;
+ UNICODE_STRING ObjectName;
+ WCHAR NdsStr[1024];
+
+ //
+ // For NwNdsResolveName.
+ //
+
+ DWORD dwOid;
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ DWORD dwHandleType;
+ HANDLE hReferredServer;
+
+ //
+ // For NwNdsReadAttribute
+ //
+ BYTE Buffer[2048];
+ DWORD BufferSize = 2048;
+ DWORD iterhandle = INITIAL_ITERATION;
+ PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
+ PNDS_ATTRIBUTE pAttribute;
+ PBYTE pAttribValue;
+
+ //
+ // Get a handle to the redirector.
+ //
+
+ Status = NwNdsOpenTreeHandle( &NDSTREE_u, &hRdr );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_TREE_OPEN_FAILED);
+ return ccode;
+ }
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+
+ if ( !Object )
+ {
+ return 1;
+ }
+
+ oemStr.Length = strlen( Object );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Object;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(NdsStr);
+ ObjectName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( hRdr,
+ &ObjectName,
+ &dwOid,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // must jump to that server before continuing.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ CloseHandle( hRdr );
+ hRdr = hReferredServer;
+ }
+
+ //
+ // Get the attribute
+ //
+
+ oemStr.Length = strlen( Property );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Property;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(NdsStr);
+ ObjectName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ Status = NwNdsReadAttribute ( hRdr,
+ dwOid,
+ &iterhandle,
+ &ObjectName,
+ Buffer,
+ BufferSize );
+
+ if ( NT_SUCCESS(Status) )
+ {
+ int i;
+ pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)Buffer;
+ pAttribute = (PNDS_ATTRIBUTE)(Buffer
+ + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
+
+ pAttribValue = (PBYTE)(pAttribute->AttribName) +
+ ROUNDUP4(pAttribute->AttribNameLength) +
+ sizeof(DWORD);
+
+ if ( pActualSize )
+ {
+ *pActualSize = *(DWORD *)pAttribValue;
+ }
+
+ memcpy( Data, pAttribValue + sizeof(DWORD),
+ min(*(DWORD *)pAttribValue, Size) );
+
+ }
+
+ NtClose( hRdr );
+
+ return Status;
+}
+
+
+/********************************************************************
+
+ NDSCleanup
+
+Routine Description:
+
+ Does any NDS cleanup
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+NDSCleanup ( void )
+{
+ NtClose( GhRdr );
+}
+
+/********************************************************************
+
+ NDSGetClassName
+
+Routine Description:
+
+ return a class name for an object
+
+Arguments:
+ szObjectName
+ ClassName
+
+Return Value:
+ none
+
+ *******************************************************************/
+unsigned int
+NDSGetClassName( LPSTR szObjectName, LPSTR ClassName )
+{
+ NTSTATUS Status;
+ int ccode = -1;
+ DWORD ThisObjectID;
+ OEM_STRING oemStr;
+ UNICODE_STRING ObjectName;
+ BYTE Buffer[2048];
+ BYTE FullName[NDS_NAME_CHARS];
+ PBYTE ptr;
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ DWORD dwHandleType;
+ HANDLE hReferredServer;
+ DWORD Length;
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+
+ oemStr.Length = strlen( szObjectName );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = szObjectName;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(Buffer);
+ ObjectName.Buffer = (WCHAR *)Buffer;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( GhRdr,
+ &ObjectName,
+ &ThisObjectID,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // should change the global handle.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ CloseHandle( GhRdr );
+ GhRdr = hReferredServer;
+ }
+
+ Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO ) + sizeof( DWORD );
+
+ RtlInitUnicodeString( &ObjectName, (PWCHAR)ptr );
+
+ oemStr.Length = 0;
+ oemStr.MaximumLength = NDS_NAME_CHARS;
+ oemStr.Buffer = ClassName;
+
+ RtlUnicodeStringToOemString( &oemStr, &ObjectName, FALSE );
+
+ return 0;
+}
diff --git a/private/nw/nwscript/nt.c b/private/nw/nwscript/nt.c
new file mode 100644
index 000000000..ebf7d4bb1
--- /dev/null
+++ b/private/nw/nwscript/nt.c
@@ -0,0 +1,617 @@
+/*************************************************************************
+*
+* NT.C
+*
+* NT NetWare routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NT.C $
+*
+* Rev 1.4 22 Dec 1995 14:25:12 terryt
+* Add Microsoft headers
+*
+* Rev 1.3 28 Nov 1995 17:13:28 terryt
+* Cleanup resource file
+*
+* Rev 1.2 22 Nov 1995 15:43:44 terryt
+* Use proper NetWare user name call
+*
+* Rev 1.1 20 Nov 1995 16:10:00 terryt
+* Close open NDS handles
+*
+* Rev 1.0 15 Nov 1995 18:07:18 terryt
+* Initial revision.
+*
+* Rev 1.2 25 Aug 1995 16:23:02 terryt
+* Capture support
+*
+* Rev 1.1 23 May 1995 19:37:02 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:10:40 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include <common.h>
+
+#include <nwapi.h>
+#include <npapi.h>
+
+#include "ntnw.h"
+/*
+ * Name of NetWare provider
+ */
+TCHAR NW_PROVIDER[60];
+unsigned char NW_PROVIDERA[60];
+
+/********************************************************************
+
+ NTPrintExtendedError
+
+Routine Description:
+
+ Print any extended errors from WNet routines
+
+Arguments:
+ None
+
+Return Value:
+ None
+
+ *******************************************************************/
+void
+NTPrintExtendedError( void )
+{
+ DWORD ExError;
+ wchar_t provider[32];
+ wchar_t description[1024];
+
+ if ( !WNetGetLastErrorW( &ExError, description, 1024, provider, 32 ) )
+ wprintf(L"%s\n", description);
+}
+
+
+/********************************************************************
+
+ NTInitProvider
+
+Routine Description:
+
+ Retrieve provider name and save old paths
+
+Arguments:
+ None
+
+Return Value:
+ None
+
+ *******************************************************************/
+void
+NTInitProvider( void )
+{
+ HKEY hKey;
+ DWORD dwType, dwSize;
+ LONG Status;
+ BOOL ret = FALSE;
+
+ dwSize = sizeof(NW_PROVIDER);
+ if ((Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_PROVIDER, 0, KEY_READ, &hKey)) == ERROR_SUCCESS) {
+ (void) RegQueryValueEx(hKey, REGISTRY_PROVIDERNAME, NULL, &dwType, (LPBYTE) NW_PROVIDER, &dwSize);
+ WideTosz( NW_PROVIDERA, NW_PROVIDER, sizeof(NW_PROVIDERA) );
+ }
+
+ RegCloseKey(hKey);
+
+ GetOldPaths();
+}
+
+/********************************************************************
+
+ DeleteDriveBase
+
+Routine Description:
+
+ Disconnect drive from network
+
+Arguments:
+
+ DriveNumber - number of drive 1-26
+
+Return Value:
+ 0 - success
+ else NetWare error
+
+ *******************************************************************/
+unsigned int
+DeleteDriveBase( unsigned short DriveNumber)
+{
+ static char drivename[] = "A:";
+ unsigned int dwRes;
+
+ drivename[0] = 'A' + DriveNumber - 1;
+
+ dwRes = WNetCancelConnection2A( drivename, 0, TRUE );
+
+ if ( dwRes != NO_ERROR )
+ dwRes = GetLastError();
+
+ if ( dwRes == ERROR_EXTENDED_ERROR )
+ NTPrintExtendedError();
+
+ return dwRes;
+}
+
+/********************************************************************
+
+ DetachFromFileServer
+
+Routine Description:
+
+ Break connection from a file server
+
+Arguments:
+
+ ConnectionId - Connection handle
+
+Return Value:
+ 0 = success
+ else NT error
+
+ *******************************************************************/
+unsigned int
+DetachFromFileServer( unsigned int ConnectionId )
+{
+ return ( NWDetachFromFileServer( (NWCONN_HANDLE)ConnectionId ) );
+}
+
+
+/********************************************************************
+
+ NTLoginToFileServer
+
+Routine Description:
+
+ Login to a file server given a user name and password.
+
+ If a NULL password is passed in, the default password should
+ be tried if no password failed.
+
+Arguments:
+
+ pszServerName - Server name
+ pszUserName - User name
+ pszPassword - Password
+
+Return Value:
+ 0 = success
+ else NetWare error
+
+ *******************************************************************/
+unsigned int
+NTLoginToFileServer(
+ char *pszServerName,
+ char *pszUserName,
+ char *pszPassword
+ )
+{
+ NETRESOURCEA NetResource;
+ DWORD dwRes;
+
+ //
+ // validate parameters
+ //
+ if (!pszServerName || !pszUserName || !pszPassword) {
+ DisplayMessage(IDR_ERROR_DURING, "NTLoginToFileServer");
+ return 0xffffffff ;
+ }
+
+ NetResource.dwScope = 0 ;
+ NetResource.dwUsage = 0 ;
+ NetResource.dwType = RESOURCETYPE_ANY;
+ NetResource.lpLocalName = NULL;
+ NetResource.lpRemoteName = pszServerName;
+ NetResource.lpComment = NULL;
+ NetResource.lpProvider = NW_PROVIDERA ;
+
+ //
+ // make the connection
+ //
+ dwRes=WNetAddConnection2A ( &NetResource,
+ pszPassword,
+ pszUserName,
+ 0 );
+ if ( dwRes != NO_ERROR )
+ dwRes = GetLastError();
+
+ //
+ // Try default password if no password was specified
+ //
+ // The error numbers aren't (or weren't) reliable (ERROR_INVALID_PASSWORD)
+ //
+ if ( ( dwRes != NO_ERROR ) && ( pszPassword[0] == '\0' ) ) {
+ dwRes=WNetAddConnection2A ( &NetResource,
+ NULL,
+ pszUserName,
+ 0 );
+ if ( dwRes != NO_ERROR )
+ dwRes = GetLastError();
+ }
+
+ return( dwRes );
+}
+
+/********************************************************************
+
+ GetFileServerName
+
+Routine Description:
+
+ Return the server name associated with the connection ID
+
+Arguments:
+
+ ConnectionId - Connection ID to a server
+ pServerName - Returned server name
+
+Return Value:
+ 0 - success
+ else NT error
+
+ *******************************************************************/
+unsigned int
+GetFileServerName(
+ unsigned int ConnectionId,
+ char * pServerName
+ )
+{
+ unsigned int Result;
+ VERSION_INFO VerInfo;
+
+ *pServerName = '\0';
+
+ Result = NWGetFileServerVersionInfo( (NWCONN_HANDLE) ConnectionId,
+ &VerInfo );
+ if ( !Result )
+ {
+ strcpy( pServerName, VerInfo.szName );
+ }
+
+ return Result;
+}
+
+/********************************************************************
+
+ SetDriveBase
+
+Routine Description:
+
+ Connect a drive to a NetWare volume
+
+Arguments:
+
+ DriveNumber - number of drive 1-26
+ ServerName - server name
+ DirHandle - not used
+ pDirPath - Volume:\Path
+
+Return Value:
+ 0 = success
+ else NetWare error
+
+ *******************************************************************/
+unsigned int
+SetDriveBase(
+ unsigned short DriveNumber,
+ unsigned char *ServerName,
+ unsigned int DirHandle,
+ unsigned char *pDirPath
+ )
+{
+ unsigned int Result = 0;
+ static char driveName[] = "A:" ;
+
+ /*
+ * DirHandle is never used
+ */
+
+ driveName[0]= 'A' + DriveNumber - 1;
+
+ if ( ( ServerName[0] == '\0' ) && fNDS ) {
+
+ /*
+ * Assume its an NDS volume name, if that fails, then
+ * try a default file server volume.
+ */
+ Result = NTSetDriveBase( driveName, NDSTREE, pDirPath );
+
+ if ( !Result )
+ return Result;
+
+ Result = NTSetDriveBase( driveName, PREFERRED_SERVER, pDirPath );
+
+ return Result;
+ }
+
+ Result = NTSetDriveBase( driveName, ServerName, pDirPath );
+
+ return Result;
+}
+
+
+/********************************************************************
+
+ NTSetDriveBase
+
+Routine Description:
+
+ Connect a local name to a NetWare volume and path
+
+Arguments:
+
+ pszLocalName - local name to connect
+ pszServerName - name of file server
+ pszDirPath - Volume:\Path
+
+Return Value:
+ 0 = success
+ else NetWare error
+
+ *******************************************************************/
+unsigned int
+NTSetDriveBase( unsigned char * pszLocalName,
+ unsigned char * pszServerName,
+ unsigned char * pszDirPath )
+{
+ NETRESOURCEA NetResource;
+ DWORD dwRes, dwSize;
+ unsigned char * pszRemoteName = NULL;
+ char * p;
+
+ //
+ // validate parameters
+ //
+ if (!pszLocalName || !pszServerName || !pszDirPath) {
+ DisplayMessage(IDR_ERROR_DURING, "NTSetDriveBase");
+ return 0xffffffff ;
+ }
+
+ //
+ // allocate memory for string
+ //
+ dwSize = strlen(pszDirPath) + strlen(pszServerName) + 5 ;
+ if (!(pszRemoteName = (unsigned char *)LocalAlloc(
+ LPTR,
+ dwSize)))
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ dwRes = 0xffffffff;
+ goto ExitPoint ;
+ }
+
+ //
+ // The requester understands
+ // server\volume:dir
+ // but not
+ // server\volume:\dir
+ //
+ // So just convert it to UNC
+ //
+
+ strcpy( pszRemoteName, "\\\\" );
+ strcat( pszRemoteName, pszServerName );
+ strcat( pszRemoteName, "\\" );
+ strcat( pszRemoteName, pszDirPath );
+
+ p = strchr( pszRemoteName, ':' );
+ if ( !p ) {
+ DisplayMessage(IDR_NO_VOLUME);
+ dwRes = 0xffffffff;
+ goto ExitPoint ;
+ }
+ *p++ = '\\';
+
+ if ( *p == '\\' ) {
+ /* Don't want a double backslash */
+ *p = '\0';
+ p = strchr( pszDirPath, ':' );
+ p++;
+ p++;
+ strcat( pszRemoteName, p );
+ }
+
+ //
+ // strip off trailing backslash
+ //
+ if (pszRemoteName[strlen(pszRemoteName)-1] == '\\')
+ pszRemoteName[strlen(pszRemoteName)-1] = '\0';
+
+ NetResource.dwScope = 0 ;
+ NetResource.dwUsage = 0 ;
+ NetResource.dwType = RESOURCETYPE_DISK;
+ NetResource.lpLocalName = pszLocalName;
+ NetResource.lpRemoteName = pszRemoteName;
+ NetResource.lpComment = NULL;
+ NetResource.lpProvider = NW_PROVIDERA ;
+
+ //
+ // make the connection
+ //
+ dwRes=WNetAddConnection2A ( &NetResource, NULL, NULL, 0 );
+
+ if ( dwRes != NO_ERROR )
+ dwRes = GetLastError();
+
+ExitPoint:
+
+ if (pszRemoteName)
+ (void) LocalFree((HLOCAL) pszRemoteName) ;
+
+ return( dwRes );
+}
+
+
+/********************************************************************
+
+ Is40Server
+
+Routine Description:
+
+ Returns TRUE if 4X server
+
+Arguments:
+
+ ConnectionHandle - Connection Handle
+
+Return Value:
+ TRUE = 4X server
+ FALSE = pre-4X server
+
+ *******************************************************************/
+unsigned int
+Is40Server(
+ unsigned int ConnectionHandle
+ )
+{
+ NTSTATUS NtStatus ;
+ VERSION_INFO VerInfo;
+ unsigned int Version;
+
+ NtStatus = NWGetFileServerVersionInfo( (NWCONN_HANDLE)ConnectionHandle,
+ &VerInfo );
+
+ if (!NT_SUCCESS(NtStatus))
+ FALSE;
+
+ Version = VerInfo.Version * 1000 + VerInfo.SubVersion * 10;
+
+ if ( Version >= 4000 ) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+/********************************************************************
+
+ CleanupExit
+
+Routine Description:
+
+ Does any cleanup and exits
+
+Arguments:
+
+ ExitCode - exit code for exit()
+
+Return Value:
+ does not return
+
+ *******************************************************************/
+void
+CleanupExit ( int ExitCode )
+{
+ if ( fNDS )
+ NDSCleanup();
+
+ exit( ExitCode );
+}
+
+/********************************************************************
+
+ NTGetNWUserName
+
+Routine Description:
+
+ Get NetWare user name
+
+Arguments:
+
+ TreeBuffer IN - wide string for server or tree
+ UserName OUT - user name
+ Length IN - length of user name
+
+Return Value:
+ error message
+
+ *******************************************************************/
+int
+NTGetNWUserName( PWCHAR TreeBuffer, PWCHAR UserName, int Length )
+{
+
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ACCESS_MASK DesiredAccess = SYNCHRONIZE | FILE_LIST_DIRECTORY;
+ HANDLE hRdr;
+
+ WCHAR DevicePreamble[] = L"\\Device\\Nwrdr\\";
+ UINT PreambleLength = 14;
+
+ WCHAR NameStr[64];
+ UNICODE_STRING OpenName;
+ UINT i;
+
+ UNICODE_STRING NdsTree;
+
+ //
+ // Copy over the preamble.
+ //
+
+ OpenName.MaximumLength = sizeof( NameStr );
+
+ for ( i = 0; i < PreambleLength ; i++ )
+ NameStr[i] = DevicePreamble[i];
+
+ RtlInitUnicodeString( &NdsTree, TreeBuffer );
+
+ //
+ // Copy the server or tree name.
+ //
+
+ for ( i = 0 ; i < ( NdsTree.Length / sizeof( WCHAR ) ) ; i++ ) {
+ NameStr[i + PreambleLength] = NdsTree.Buffer[i];
+ }
+
+ OpenName.Length = ( i * sizeof( WCHAR ) ) +
+ ( PreambleLength * sizeof( WCHAR ) );
+ OpenName.Buffer = NameStr;
+
+ //
+ // Set up the object attributes.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ &OpenName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ ntstatus = NtOpenFile( &hRdr,
+ DesiredAccess,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_SYNCHRONOUS_IO_NONALERT );
+
+ if ( !NT_SUCCESS(ntstatus) )
+ return ntstatus;
+
+ ntstatus = NtFsControlFile( hRdr,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_NWR_GET_USERNAME,
+ (PVOID) TreeBuffer,
+ NdsTree.Length,
+ (PVOID) UserName,
+ Length );
+
+ UserName[(USHORT)IoStatusBlock.Information/2] = 0;
+
+ NtClose( hRdr );
+ return ntstatus;
+
+}
diff --git a/private/nw/nwscript/ntcap.c b/private/nw/nwscript/ntcap.c
new file mode 100644
index 000000000..64dc75648
--- /dev/null
+++ b/private/nw/nwscript/ntcap.c
@@ -0,0 +1,329 @@
+/*************************************************************************
+*
+* NTCAP.C
+*
+* NT NetWare routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NTCAP.C $
+*
+* Rev 1.2 10 Apr 1996 14:23:04 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:54:36 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:25:20 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:07:20 terryt
+* Initial revision.
+*
+* Rev 1.0 25 Aug 1995 15:41:14 terryt
+* Initial revision.
+*
+*
+*************************************************************************/
+
+#include "common.h"
+#include <ntddnwfs.h>
+#include <nwapi.h>
+#include <npapi.h>
+#include "ntnw.h"
+
+extern unsigned char NW_PROVIDERA[];
+
+/********************************************************************
+
+ EndCapture
+
+Routine Description:
+
+ Remove the local printer redirection
+
+Arguments:
+ LPTDevice - IN
+ 1, 2, or 3 - the local printer #
+
+Return Value:
+ Error
+
+ *******************************************************************/
+unsigned int
+EndCapture(
+ unsigned char LPTDevice
+ )
+{
+ char LPTname[] = "LPT1";
+ unsigned int dwRes;
+
+ LPTname[3] = '1' + LPTDevice - 1;
+
+ /*
+ * Should we check for non-NetWare printers?
+ */
+
+ dwRes = WNetCancelConnection2A( LPTname, 0, TRUE );
+
+ if ( dwRes != NO_ERROR )
+ dwRes = GetLastError();
+
+ if ( dwRes == ERROR_EXTENDED_ERROR )
+ NTPrintExtendedError();
+
+ return dwRes;
+}
+
+
+/********************************************************************
+
+ GetCaptureFlags
+
+Routine Description:
+
+ Return info about the printer capture status. Note that the only
+ options set on NT are on a per-user basis and can be changed with
+ the control panel.
+
+Arguments:
+ LPTDevice - IN
+ LPT device 1, 2 or 3
+ pCaptureFlagsRW - OUT
+ Capture options
+ pCaptureFlagsRO - OUT
+ Capture options
+
+Return Value:
+
+ *******************************************************************/
+unsigned int
+GetCaptureFlags(
+ unsigned char LPTDevice,
+ PNETWARE_CAPTURE_FLAGS_RW pCaptureFlagsRW,
+ PNETWARE_CAPTURE_FLAGS_RO pCaptureFlagsRO
+ )
+{
+ LPBYTE Buffer ;
+ DWORD dwErr ;
+ HANDLE EnumHandle ;
+ DWORD Count ;
+ char LPTName[10];
+ DWORD BufferSize = 4096;
+ char *remotename;
+ char *p;
+ DWORD dwPrintOptions ;
+ LPTSTR pszPreferred ;
+
+ strcpy( LPTName, "LPT1" );
+
+ LPTName[3] = '1' + LPTDevice - 1;
+
+ pCaptureFlagsRO->LPTCaptureFlag = 0;
+
+ //
+ // allocate memory and open the enumeration
+ //
+ if (!(Buffer = LocalAlloc( LPTR, BufferSize ))) {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return 0xFFFF;
+ }
+
+ dwErr = WNetOpenEnum(RESOURCE_CONNECTED, 0, 0, NULL, &EnumHandle) ;
+ if (dwErr != WN_SUCCESS) {
+ dwErr = GetLastError();
+ if ( dwErr == ERROR_EXTENDED_ERROR )
+ NTPrintExtendedError();
+ (void) LocalFree((HLOCAL) Buffer) ;
+ return 0xFFFF;
+ }
+
+ do {
+
+ Count = 0xFFFFFFFF ;
+ BufferSize = 4096;
+ dwErr = WNetEnumResourceA(EnumHandle, &Count, Buffer, &BufferSize) ;
+
+ if ((dwErr == WN_SUCCESS || dwErr == WN_NO_MORE_ENTRIES)
+ && ( Count != 0xFFFFFFFF) )
+ {
+ LPNETRESOURCEA lpNetResource ;
+ DWORD i ;
+
+ lpNetResource = (LPNETRESOURCEA) Buffer ;
+
+ //
+ // search for our printer
+ //
+ for ( i = 0; i < Count; lpNetResource++, i++ )
+ {
+ if ( lpNetResource->lpLocalName )
+ {
+ if ( !_strcmpi(lpNetResource->lpLocalName, LPTName ))
+ {
+ if ( lpNetResource->lpProvider )
+ {
+ if ( _strcmpi( lpNetResource->lpProvider,
+ NW_PROVIDERA ) )
+ {
+
+ pCaptureFlagsRO->LPTCaptureFlag = 0;
+ }
+ else
+ {
+ remotename = lpNetResource->lpRemoteName;
+ p = strchr (remotename + 2, '\\');
+ if ( !p )
+ return 0xffffffff;
+ *p++ = '\0';
+ _strupr( remotename+2 );
+ _strupr( p );
+ strcpy( pCaptureFlagsRO->ServerName, remotename+2 );
+ strcpy( pCaptureFlagsRO->QueueName, p );
+ pCaptureFlagsRO->LPTCaptureFlag = 1;
+
+ pCaptureFlagsRW->JobControlFlags = 0;
+ pCaptureFlagsRW->TabSize = 8;
+ pCaptureFlagsRW->NumCopies = 1;
+ //
+ // query NW wksta for print options
+ // & preferred server
+ //
+ if ( NwQueryInfo(&dwPrintOptions,
+ &pszPreferred)) {
+ pCaptureFlagsRW->PrintFlags =
+ CAPTURE_FLAG_NOTIFY |
+ CAPTURE_FLAG_PRINT_BANNER ;
+ }
+ else {
+ pCaptureFlagsRW->PrintFlags = 0;
+ if ( dwPrintOptions & NW_PRINT_PRINT_NOTIFY )
+ pCaptureFlagsRW->PrintFlags |=
+ CAPTURE_FLAG_NOTIFY;
+ if ( dwPrintOptions & NW_PRINT_SUPPRESS_FORMFEED)
+ pCaptureFlagsRW->PrintFlags |=
+ CAPTURE_FLAG_NO_FORMFEED;
+ if ( dwPrintOptions & NW_PRINT_PRINT_BANNER )
+ pCaptureFlagsRW->PrintFlags |=
+ CAPTURE_FLAG_PRINT_BANNER;
+ }
+ pCaptureFlagsRW->FormName[0] = 0;
+ pCaptureFlagsRW->FormType = 0;
+ pCaptureFlagsRW->BannerText[0] = 0;
+ pCaptureFlagsRW->FlushCaptureTimeout = 0;
+ pCaptureFlagsRW->FlushCaptureOnClose = 1;
+ }
+ }
+ else
+ {
+ pCaptureFlagsRO->LPTCaptureFlag = 0;
+ }
+
+ (void) WNetCloseEnum(EnumHandle) ;
+ (void) LocalFree((HLOCAL) Buffer) ;
+ return 0;
+ }
+ }
+ }
+ }
+
+ } while (dwErr == WN_SUCCESS) ;
+
+ if ( ( dwErr != WN_SUCCESS ) && ( dwErr != WN_NO_MORE_ENTRIES ) )
+ {
+ dwErr = GetLastError();
+ if ( dwErr == ERROR_EXTENDED_ERROR )
+ NTPrintExtendedError();
+ }
+
+ (void ) WNetCloseEnum(EnumHandle) ;
+ (void) LocalFree((HLOCAL) Buffer) ;
+
+ return 0;
+}
+
+/********************************************************************
+
+ StartQueueCapture
+
+Routine Description:
+
+ Attach local name to the queue.
+
+
+Arguments:
+ ConnectionHandle - IN
+ Handle to file server
+ LPTDevice - IN
+ LPT 1, 2 or 3
+ pServerName - IN
+ Server name
+ pQueueName - IN
+ Printer queue name
+
+Return Value:
+
+ *******************************************************************/
+unsigned int
+StartQueueCapture(
+ unsigned int ConnectionHandle,
+ unsigned char LPTDevice,
+ unsigned char *pServerName,
+ unsigned char *pQueueName
+ )
+{
+ NETRESOURCEA NetResource;
+ DWORD dwRes, dwSize;
+ unsigned char * pszRemoteName = NULL;
+ unsigned char pszLocalName[10];
+ char * p;
+
+ //
+ // validate parameters
+ //
+ if (!pServerName || !pQueueName || !LPTDevice) {
+ DisplayMessage(IDR_ERROR_DURING, "StartQueueCapture");
+ return 0xffffffff ;
+ }
+
+ //
+ // allocate memory for string
+ //
+ dwSize = strlen(pServerName) + strlen(pQueueName) + 5 ;
+ if (!(pszRemoteName = (unsigned char *)LocalAlloc(
+ LPTR,
+ dwSize)))
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ dwRes = 0xffffffff;
+ goto ExitPoint ;
+ }
+
+ sprintf(pszRemoteName, "\\\\%s\\%s", pServerName, pQueueName);
+ sprintf(pszLocalName, "LPT%d", LPTDevice );
+
+ NetResource.dwScope = 0 ;
+ NetResource.dwUsage = 0 ;
+ NetResource.dwType = RESOURCETYPE_PRINT;
+ NetResource.lpLocalName = pszLocalName;
+ NetResource.lpRemoteName = pszRemoteName;
+ NetResource.lpComment = NULL;
+ NetResource.lpProvider = NW_PROVIDERA ;
+
+ //
+ // make the connection
+ //
+ dwRes=WNetAddConnection2A ( &NetResource, NULL, NULL, 0 );
+
+ if ( dwRes != NO_ERROR )
+ dwRes = GetLastError();
+
+ExitPoint:
+
+ if (pszRemoteName)
+ (void) LocalFree((HLOCAL) pszRemoteName) ;
+
+ return( dwRes );
+}
+
+
diff --git a/private/nw/nwscript/ntnw.c b/private/nw/nwscript/ntnw.c
new file mode 100644
index 000000000..00cf54057
--- /dev/null
+++ b/private/nw/nwscript/ntnw.c
@@ -0,0 +1,163 @@
+/*************************************************************************
+*
+* NTNW.C
+*
+* Dos NetWare to NT NetWare translation
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NTNW.C $
+*
+* Rev 1.1 22 Dec 1995 14:25:28 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:07:24 terryt
+* Initial revision.
+*
+* Rev 1.2 25 Aug 1995 16:23:08 terryt
+* Capture support
+*
+* Rev 1.1 23 May 1995 19:37:10 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:10:44 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include "common.h"
+
+extern int CONNECTION_ID;
+
+/********************************************************************
+
+ NTGetCurrentDirectory
+
+Routine Description:
+
+ Return the current directory.
+
+Arguments:
+
+ DriveNumber = The drive to get the directory from.
+ (0 = A, 1 = B, 2 = C, etc)
+ pPath = A pointer to a 64 byte buffer to return the
+ current directory.
+
+Return Value:
+
+ 0 Success
+ else Error
+
+ ********************************************************************/
+
+unsigned int
+NTGetCurrentDirectory(
+ unsigned char DriveNumber,
+ unsigned char *pPath
+ )
+{
+ char * CurPath;
+ int currentDrive = _getdrive() ;
+
+ //
+ // Change to the drive and get its current working directory.
+ // Default to root if fail to get cwd. DriveNumber is from 0.
+ //
+
+ _chdrive (DriveNumber+1);
+
+ CurPath = _getcwd(NULL,MAX_PATH) ;
+
+ if ( CurPath != NULL ) {
+
+ strcpy( pPath, CurPath );
+ free(CurPath) ;
+ }
+ else {
+
+ strcpy( pPath, "A:\\" );
+ pPath[0] += DriveNumber;
+ }
+
+ _chdrive (currentDrive);
+
+ return 0;
+}
+
+/********************************************************************
+
+ AttachToFileServer
+
+Routine Description:
+
+ Attach to a named file server
+
+Arguments:
+
+ pServerName - Name of server
+ pNewConnectionId - returned connection handle
+
+Return Value:
+ 0 = success
+ else NetWare error
+
+ *******************************************************************/
+unsigned int
+AttachToFileServer(
+ unsigned char *pServerName,
+ unsigned int *pNewConnectionId
+ )
+{
+ unsigned int Result;
+
+ if ( NTIsConnected( pServerName ) ) {
+ return 0x8800; // Already atached.
+ }
+
+ Result = NTAttachToFileServer( pServerName, pNewConnectionId );
+
+ return Result;
+}
+
+/********************************************************************
+
+ GetConnectionHandle
+
+Routine Description:
+
+ Given a server name, return the connection handle.
+ The server should already be attached
+ Note that this is not called for 4X servers. It's used
+ for attaches and bindery connections.
+
+Arguments:
+
+ pServerName - Name of server
+ pConnectionHandle - pointer to returned connection handle
+
+Return Value:
+ 0 = success
+ else NetWare error
+
+ *******************************************************************/
+unsigned int
+GetConnectionHandle(
+ unsigned char *pServerName,
+ unsigned int *pConnectionHandle
+ )
+{
+ unsigned int Result;
+
+ if ( !NTIsConnected( pServerName ) ) {
+ return 0xFFFF; // not already connected
+ }
+
+ Result = NTAttachToFileServer( pServerName, pConnectionHandle );
+
+ return Result;
+}
+
diff --git a/private/nw/nwscript/ntscript.c b/private/nw/nwscript/ntscript.c
new file mode 100644
index 000000000..b29d9beba
--- /dev/null
+++ b/private/nw/nwscript/ntscript.c
@@ -0,0 +1,304 @@
+/*************************************************************************
+*
+* NTSCRIPT.C
+*
+* Process all login scripts
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NTSCRIPT.C $
+*
+* Rev 1.8 10 Apr 1996 14:23:12 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.9 12 Mar 1996 19:54:58 terryt
+* Relative NDS names and merge
+*
+* Rev 1.8 07 Mar 1996 18:36:56 terryt
+* Misc fixes
+*
+* Rev 1.7 22 Jan 1996 16:48:26 terryt
+* Add automatic attach query during map
+*
+* Rev 1.6 08 Jan 1996 13:57:58 terryt
+* Correct NDS Preferred Server
+*
+* Rev 1.5 05 Jan 1996 17:18:26 terryt
+* Ensure context is the correct login default
+*
+* Rev 1.4 04 Jan 1996 18:56:48 terryt
+* Bug fixes reported by MS
+*
+* Rev 1.3 22 Dec 1995 11:08:16 terryt
+* Fixes
+*
+* Rev 1.2 22 Nov 1995 15:43:52 terryt
+* Use proper NetWare user name call
+*
+* Rev 1.1 20 Nov 1995 15:09:38 terryt
+* Context and capture changes
+*
+* Rev 1.0 15 Nov 1995 18:07:28 terryt
+* Initial revision.
+*
+* Rev 1.2 25 Aug 1995 16:23:14 terryt
+* Capture support
+*
+* Rev 1.1 26 Jul 1995 16:02:00 terryt
+* Allow deletion of current drive
+*
+* Rev 1.0 15 May 1995 19:10:46 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <direct.h>
+#include <process.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "common.h"
+
+#include "inc/ntnw.h"
+
+#include <nwapi.h>
+
+void ProcessLoginScripts(unsigned int conn, char * UserName, int argc, char **argv, char *lpScript);
+
+extern int SafeDisk;
+
+extern unsigned int ConvertNDSPathToNetWarePath(char *, char *, char *);
+
+/*************************************************************************
+*
+* NTNetWareLoginScripts
+* Main logon script processor
+*
+* ENTRY:
+*
+* EXIT
+*
+*************************************************************************/
+
+int
+NTNetWareLoginScripts( int argc, char ** argv )
+{
+ unsigned int defConn;
+ char UserName[MAX_NAME_LEN]="";
+ WCHAR UserName_w[MAX_NAME_LEN * sizeof(WCHAR)]=L"";
+ char MessageServer[NDS_NAME_CHARS]="";
+ char *lpScript = NULL;
+ DWORD PrintOptions;
+ LPTSTR pszPreferredSrv;
+ LPTSTR ptreeW;
+ LPTSTR pcontextW;
+ NTSTATUS ntstatus;
+ char * lpC1;
+ char * lpC2;
+ unsigned int NewConn;
+ unsigned int Result;
+
+ if ( NwQueryInfo( &PrintOptions, &pszPreferredSrv ) || !pszPreferredSrv )
+ {
+ DisplayMessage(IDR_QUERY_INFO_FAILED);
+ return( FALSE );
+ }
+
+ //
+ // nwscript /S filename
+ //
+ // can be used to pass a local script file for testing
+ //
+ if ( ( argc >= 3 ) && !_strcmpi(argv[1], "/S") )
+ {
+ lpScript = argv[2];
+ argc -= 2;
+ argv += 2;
+ }
+
+ //
+ // NDS preferred server format is:
+ // *<tree name>\<context>
+
+ fNDS = ( *pszPreferredSrv == L'*' );
+
+ if ( fNDS )
+ {
+
+ // Get the NDS tree name
+
+ ptreeW = pszPreferredSrv + 1;
+
+ pcontextW = wcschr( pszPreferredSrv, L'\\' );
+
+ if ( pcontextW )
+ {
+ *pcontextW++ = L'\0';
+ }
+
+ NDSTREE = malloc ( CONTEXT_MAX );
+ NDSTREE_w = malloc ( CONTEXT_MAX * sizeof(WCHAR) );
+ if ( ptreeW )
+ {
+ wcscpy( NDSTREE_w, ptreeW );
+ RtlInitUnicodeString( &NDSTREE_u, NDSTREE_w );
+ WideTosz( NDSTREE, ptreeW, CONTEXT_MAX );
+ _strupr( NDSTREE );
+ }
+ else
+ {
+ strcpy( NDSTREE, "" );
+ wcscpy( NDSTREE_w, L"" );
+ }
+
+ // Get the fully typed user name
+
+ TYPED_USER_NAME_w = malloc ( sizeof(WCHAR) * NDS_NAME_CHARS );
+ TYPED_USER_NAME = malloc ( NDS_NAME_CHARS );
+
+ ntstatus = NTGetNWUserName( NDSTREE_w, TYPED_USER_NAME_w,
+ sizeof(WCHAR) * NDS_NAME_CHARS );
+ if ( !NT_SUCCESS( ntstatus ) ) {
+ DisplayMessage(IDR_QUERY_INFO_FAILED);
+ return ( FALSE );
+ }
+
+ WideTosz( TYPED_USER_NAME, TYPED_USER_NAME_w, NDS_NAME_CHARS );
+
+ // Get the user name stripped of context and type
+
+ lpC1 = strchr( TYPED_USER_NAME, '=' );
+ if ( lpC1 )
+ lpC1++;
+ else
+ lpC1 = TYPED_USER_NAME;
+
+ lpC2 = strchr( TYPED_USER_NAME, '.' );
+
+ if ( lpC2 )
+ strncpy( UserName, lpC1, lpC2 - lpC1 );
+ else
+ strcpy( UserName, lpC1 );
+
+ // Get the default context
+ // This should be where the user is
+
+ REQUESTER_CONTEXT = malloc( CONTEXT_MAX );
+
+ if ( lpC2 )
+ {
+ strcpy( REQUESTER_CONTEXT, lpC2+1 );
+ }
+ else
+ {
+ strcpy( REQUESTER_CONTEXT, "" );
+ }
+ NDSTypeless( REQUESTER_CONTEXT, REQUESTER_CONTEXT );
+
+ //
+ // This finishes the NDS initialization
+ //
+ if ( NDSInitUserProperty () )
+ return ( FALSE );
+
+ }
+ else
+ {
+ ntstatus = NTGetNWUserName( pszPreferredSrv, UserName_w,
+ MAX_NAME_LEN * sizeof(WCHAR) );
+ if ( !NT_SUCCESS( ntstatus ) ) {
+ DisplayMessage(IDR_QUERY_INFO_FAILED);
+ return ( FALSE );
+ }
+ WideTosz( UserName, UserName_w, MAX_NAME_LEN );
+ _strupr( UserName );
+ }
+
+ //
+ // If we map over a drive, the SafeDisk is used.
+ //
+ SafeDisk = _getdrive();
+
+ NTInitProvider();
+
+ //
+ // Get the default connection handle.
+ //
+ // This is used to get the preferred server!
+
+ if ( !CGetDefaultConnectionID (&defConn) )
+ return( FALSE );
+
+ PREFERRED_SERVER = malloc( NDS_NAME_CHARS );
+
+ GetFileServerName(defConn, PREFERRED_SERVER);
+
+ //
+ // By default we are "attached" to the default server
+ //
+ if ( fNDS )
+ AddServerToAttachList( PREFERRED_SERVER, LIST_4X_SERVER );
+ else
+ AddServerToAttachList( PREFERRED_SERVER, LIST_3X_SERVER );
+
+ //
+ // Print out status
+ //
+ if ( fNDS )
+ {
+ DisplayMessage( IDR_CURRENT_CONTEXT, REQUESTER_CONTEXT );
+ DisplayMessage( IDR_CURRENT_TREE, NDSTREE_w );
+ }
+
+ DisplayMessage( IDR_CURRENT_SERVER, PREFERRED_SERVER );
+
+ //
+ // We may want to change the Preferred Server based on the DS.
+ // "MESSAGE_SERVER" should be the Preferred Server (if possible).
+ //
+ if ( fNDS )
+ {
+ NDSGetVar ( "MESSAGE_SERVER", MessageServer, NDS_NAME_CHARS );
+ if ( strlen( MessageServer ) )
+ {
+ NDSAbbreviateName(FLAGS_NO_CONTEXT, MessageServer, MessageServer);
+ lpC1 = strchr( MessageServer, '.' );
+ if ( lpC1 )
+ *lpC1 = '\0';
+ if ( strcmp( MessageServer, PREFERRED_SERVER) )
+ {
+ DisplayMessage( IDR_AUTHENTICATING_SERVER, MessageServer );
+ Result = NTAttachToFileServer( MessageServer, &NewConn );
+ if ( Result )
+ {
+ DisplayMessage( IDR_SERVER_NOT_FOUND, MessageServer );
+ }
+ else
+ {
+ NWDetachFromFileServer( (NWCONN_HANDLE)NewConn );
+ strncpy( PREFERRED_SERVER, MessageServer, NDS_NAME_CHARS);
+ DisplayMessage( IDR_CURRENT_SERVER, PREFERRED_SERVER );
+
+ // By default we are "attached" to the preferred server
+
+ AddServerToAttachList( PREFERRED_SERVER, LIST_4X_SERVER );
+ }
+ }
+ }
+ }
+
+ //
+ // Just like login we ignore any errors from setting the login
+ // directory.
+ //
+ SetLoginDirectory (PREFERRED_SERVER);
+
+ // Process login scripts.
+
+ ProcessLoginScripts(defConn, UserName, argc, argv, lpScript);
+
+ return( TRUE );
+}
diff --git a/private/nw/nwscript/nwapi1.c b/private/nw/nwscript/nwapi1.c
new file mode 100644
index 000000000..a7a8c30c6
--- /dev/null
+++ b/private/nw/nwscript/nwapi1.c
@@ -0,0 +1,47 @@
+
+/*************************************************************************
+*
+* NWAPI1.C
+*
+* NetWare routines, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NWAPI1.C $
+*
+* Rev 1.1 22 Dec 1995 14:25:48 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:07:32 terryt
+* Initial revision.
+*
+* Rev 1.0 15 May 1995 19:10:48 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include "common.h"
+
+/*
+ Get default connection handle.
+ return TRUE if succeeded, FALSE otherwise.
+ */
+int CGetDefaultConnectionID ( unsigned int * pConn )
+{
+ unsigned int iRet = GetDefaultConnectionID(pConn);
+
+ switch (iRet)
+ {
+ case 0:
+ break;
+
+ case 0x880f:
+ DisplayMessage(IDR_NO_KNOWN_FILE_SERVER);
+ break;
+ default:
+ DisplayMessage(IDR_NO_DEFAULT_CONNECTION);
+ break;
+ }
+
+ return(iRet == 0);
+}
+
diff --git a/private/nw/nwscript/nwapi2.c b/private/nw/nwscript/nwapi2.c
new file mode 100644
index 000000000..31e0d669b
--- /dev/null
+++ b/private/nw/nwscript/nwapi2.c
@@ -0,0 +1,49 @@
+
+/*************************************************************************
+*
+* NWAPI2.C
+*
+* NetWare routines, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NWAPI2.C $
+*
+* Rev 1.1 22 Dec 1995 14:25:54 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:07:34 terryt
+* Initial revision.
+*
+* Rev 1.0 15 May 1995 19:10:50 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <direct.h>
+#include "common.h"
+
+/*
+ Set the current drive to the login directory
+ of the default server.
+ */
+void SetLoginDirectory( PBYTE serverName )
+{
+ unsigned int iRet = 0;
+ WORD firstDrive;
+
+ if(iRet = GetFirstDrive (&firstDrive))
+ {
+ DisplayError(iRet,"GetFirstDrive");
+ return;
+ }
+
+ // Nothing we can do if SetDriveBase failed.
+ // Don't report the error.
+
+ if ( !( SetDriveBase (firstDrive, serverName, 0, "SYS:LOGIN") ) )
+ {
+ _chdrive (firstDrive);
+ ExportCurrentDrive( firstDrive );
+ }
+}
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);
+}
diff --git a/private/nw/nwscript/nwscript.c b/private/nw/nwscript/nwscript.c
new file mode 100644
index 000000000..f56e23ff0
--- /dev/null
+++ b/private/nw/nwscript/nwscript.c
@@ -0,0 +1,84 @@
+/*************************************************************************
+*
+* NWSCRIPT.C
+*
+* This module is the NetWare Logon Script utility.
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\NWSCRIPT.C $
+*
+* Rev 1.3 22 Jan 1996 16:48:32 terryt
+* Add automatic attach query during map
+*
+* Rev 1.2 22 Dec 1995 14:26:08 terryt
+* Add Microsoft headers
+*
+* Rev 1.1 20 Nov 1995 16:10:38 terryt
+* Close open NDS handles
+*
+* Rev 1.0 15 Nov 1995 18:07:42 terryt
+* Initial revision.
+*
+* Rev 1.1 23 May 1995 19:37:18 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:10:58 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <stdio.h>
+#include <windows.h>
+#include <stdlib.h>
+#include <time.h>
+#include <direct.h>
+#include <process.h>
+#include <string.h>
+#include <malloc.h>
+#include <nwapi.h>
+
+#include "nwscript.h"
+
+int NTNetWareLoginScripts( int argc, char ** argv );
+
+unsigned int fNDS = FALSE;
+
+/*************************************************************************
+*
+* main
+* Main function and entry point
+*
+* ENTRY:
+* argc (input)
+* count of the command line arguments.
+* argv (input)
+* vector of strings containing the command line arguments;
+* (not used due to always being ANSI strings).
+*
+* EXIT
+* (int) exit code: SUCCESS for success; FAILURE for error.
+*
+*************************************************************************/
+
+int _CRTAPI1
+main( int argc,
+ char **argv )
+{
+ //
+ // Call wksta to reset the sync login script flag if it did set it.
+ // This flag is set and reset everytime so that if nw login scripts
+ // are not used, user does not need wait.
+ // Ignore any errors.
+ //
+ (void) NwSetLogonScript(RESET_SYNC_LOGONSCRIPT) ;
+
+ (void)NTNetWareLoginScripts( argc, argv );
+
+ CleanupExit( 0 );
+
+ return 0;
+
+} /* main() */
+
+
diff --git a/private/nw/nwscript/nwscript.rc b/private/nw/nwscript/nwscript.rc
new file mode 100644
index 000000000..96c646176
--- /dev/null
+++ b/private/nw/nwscript/nwscript.rc
@@ -0,0 +1,243 @@
+#ifdef NOMINMAX
+#undef NOMINMAX
+#endif
+
+#include <winver.h>
+#include <ntverp.h>
+#include "nwscript.h"
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "NetWare Logon Script Utility"
+#define VER_INTERNALNAME_STR "nwscript"
+#define VER_ORIGINALFILENAME_STR "nwscript.exe"
+
+// #define VER_LEGALCOPYRIGHT_STR VER_LEGALCOPYRIGHT_STR
+#undef VER_ADDITIONALCOPYRIGHT_STR
+
+#include "common.ver"
+
+STRINGTABLE
+BEGIN
+ IDR_ERROR
+ "Error: unexpected error 0x%x during %S\n"
+ IDR_NO_DEFAULT_CONNECTION
+ "Error: Unable to get default connection.\n\a"
+ IDR_NO_KNOWN_FILE_SERVER
+ "No known file server.\n"
+ IDR_LOCAL_DRIVE
+ "Drive %C: maps to a local disk.\n"
+ IDR_NETWARE_DRIVE
+ "Drive %C: = %S \\%S\n"
+ IDR_DASHED_LINE
+ " ----- Search Drives -----\n"
+ IDR_LOCAL_SEARCH
+ "S%d: = %S\n"
+ IDR_NETWARE_SEARCH
+ "S%d: = %S [%S \\%S]\n"
+ IDR_NOT_ENOUGH_MEMORY
+ "Error: Not enough memory.\n"
+ IDR_NO_RESPONSE
+ "No response from file server %S.\n"
+ IDR_PASSWORD
+ "Enter the password for user %S on server %S: "
+ IDR_ATTACHED
+ "You are attached to server %S.\n\n"
+ IDR_ACCESS_DENIED
+ "Access denied.\n"
+ IDR_UNAUTHORIZED_LOGIN_TIME
+ "Attempt to login during an unauthorized time period.\nThe supervisor has limited the times that you can login to this server.\n"
+ IDR_LOGIN_DENIED_NO_CONNECTION
+ "Attempting to simultaneously login to too many work stations.\nThe supervisor has limited the number of active connections you may have.\n"
+ IDR_UNAUTHORIZED_LOGIN_STATION
+ "Attempting to login from an unapproved station.\nThe supervisor has limited the stations that you are allowed to login on.\n"
+ IDR_ACCOUNT_DISABLED
+ "This account has expired or been disabled by the supervisor.\n"
+ IDR_PASSWORD_EXPRIED_NO_GRACE
+ "Password has expired and all grace logins have been used.\n"
+ IDR_MAP_NOT_ATTACHED_SERVER
+ "Attempt to map drive to server to which you are not currently attached.\nThe map command was ""%S"".\n"
+ IDR_MAP_USAGE
+ "Microsoft (R) MAP Utility\nCopyright (C) Microsoft Corporation 1994. All rights reserved.\n\n View current mapping.\n\tMAP [drive:]\nCreate or change network drive mappings\n\tMAP path\n\tMAP drive:=[drive:|path]\n\tMAP [DEL[ete] | REM[ove]] drive:\n Create or change search drive mappings\n\tMAP [INS[ert]] drive:=[drive:|path]\nMap a drive to a fake root directory\n\tMAP ROOT drive:=[drive:|path]\nMap the next available drive\n\tMAP N[ext] [drive:|path]\n"
+ IDR_UNDEFINED
+ "Drive %C: is not defined.\n"
+ IDR_DIRECTORY_NOT_FOUND
+ "Directory ""%S"" is not locatable.\n"
+ IDR_VOLUME_NOT_EXIST
+ "Volume ""%S"" does not exist.\n"
+ IDR_WRONG_DRIVE
+ "Attempted operation on invalid drive %C:\n"
+ IDR_DEL_DRIVE
+ "Mapping for drive %C: has been deleted.\n"
+ IDR_DEL_SEARCH_DRIVE
+ "The search mapping for drive %C: has been deleted.\n"
+ IDR_SEARCH_DRIVE_NOT_EXIST
+ "Search%d: does not exist.\n"
+ IDR_NOT_NETWORK_DRIVE
+ "Attempt to map network drive to unmapped drive or local drive.\n"
+ IDR_NO_DRIVE_AVAIL
+ "All Drives are in use.\n"
+ IDR_INVALID_PATH
+ """%S"" Invalid path.\n"
+ IDR_CAN_NOT_CHANGE_DRIVE
+ "Can not change the drive mapping.\n"
+ IDR_MAP_INVALID_PATH
+ "Attempt to map drive to invalid path in map command ""%S"".\n"
+ IDR_MAP_FAILED
+ "Following drive mapping operation could not be completed.\r\n ""%S""\r\n"
+ IDR_NO_SCRIPT_FILE
+ "Cannot open this script file: %S\n"
+ IDR_STRIKE_KEY
+ "Strike any key when ready . . ."
+ IDR_CANNOT_EXECUTE
+ "Could not execute external program ""%S"".\n"
+ IDR_ENOENT
+ "Could not execute external program ""%S"", program not found.\n"
+ IDR_EXIT_NOT_SUPPORTED
+ "The EXIT command followed by a string is not supported on this machine.\n"
+ IDR_IF_TOO_DEEP
+ "Script Error: ""IF"" statements nested too deeply. The nesting limit is 9 levels.\n"
+ IDR_SCRIPT_ERROR
+ "Script Error: Could not interpret line.\n"
+ IDR_ORIGINAL_LINE_WAS
+ "The original line was:\r\n%S\n\n"
+ IDR_BAD_COMMAND
+ "Bad command or file name.\n"
+ IDR_LABEL_NOT_FOUND
+ "Could not find label ""%S"".\n"
+ IDR_NO_VOLUME
+ "Error: No volume found.\n"
+ IDR_ERROR_DURING
+ "Error: unexpected error during %S\n"
+ IDR_MAP_ERROR
+ "%x\n"
+ IDR_ENTER_SERVER_NAME
+ "Enter the server name: "
+ IDR_ENTER_LOGIN_NAME
+ "Enter login name for server %S: "
+ IDR_ERROR_SET_DEFAULT_DRIVE
+ "Could not set the default drive to drive %C:.\n\n"
+ IDR_ERROR_OPEN_SCRIPT
+ "Cannot open this script file: %S\n"
+ IDR_DIVIDE_BY_ZERO
+ "Attempted to divide by zero\n"
+ IDR_NEWLINE
+ "\n"
+ IDR_SERVER_USER
+ "%S/%S: "
+ IDR_NON_NETWARE_NETWORK_DRIVE
+ "Following drive mapping operation was attempted on a non-NetWare network drive.\r\n ""%S""\r\n"
+ IDR_CAPTURE_USAGE
+ "Microsoft (R) CAPTURE Utility\nCopyright (C) Microsoft Corporation 1994. All rights reserved.\n\n USAGE: CAPTURE /SHow /Server=fileserver /Queue=queuename /Local=n\n /Form=form or n /CReate=path /Copies=n (1-255) /TImeout=n /Keep /Tabs=n (1-18) /No Tabs /Banner=bannername /NAMe=name /No Banner /FormFeed /No FormFeed\n /AUtoendcap /No Autoend /NOTIfy /No NOTIfy\n"
+
+ IDR_NOT_ACTIVE
+ "\nLPT%d: Capturing Is Not Currently Active.\n"
+ IDR_LPT_STATUS
+ "\n LPT%d: Capturing data to server %S queue %S.\n %s\n Capture Defaults:%-15sAutomatic Endcap:%s\n Banner :%-24SForm Feed :%s\n Copies :%-24dTabs :%s\n Form :%-24dTimeout Count :%s\n"
+ IDR_LPT_STATUS_NO_BANNER
+ "\n LPT%d: Capturing data to server %S queue %S.\n %s\n Capture Defaults:%-15sAutomatic Endcap:%s\n Banner :%-24sForm Feed :%s\n Copies :%-24dTabs :%s\n Form :%-24dTimeout Count :%s\n"
+ IDR_UNKNOW_FLAG
+ "An unknown flag %S was encountered.\n"
+ IDR_INVALID_LPT_NUMBER
+ "Local printer number (1, 2, or 3) expected.\n"
+ IDR_SERVER_NOT_FOUND
+ "Unable to attach to server %S.\n"
+ IDR_TIMEOUT_OUTOF_RANGE
+ "Timeout value (0-1000) expected.\n"
+ IDR_TABSIZE_OUTOF_RANGE
+ "Tab size must be 1 - 18.\n"
+ IDR_COPIES_OUTOF_RANGE
+ "Number of copies (1-255) expected.\n"
+ IDR_INVALID_BANNER
+ "%S is invalid banner.\n"
+ IDR_INVALID_FORM_NAME
+ "%S is invalid form name.\n"
+ IDR_INVALID_FORM_TYPE
+ "Form type (0-255) expected.\n"
+ IDR_SUCCESS_QUEUE
+ "Device LPT%d: re-routed to queue %S on server %S.\n"
+ IDR_NO_PRINTERS
+ "No default queue name can be found on server %S.\n"
+ IDR_QUEUE_NOT_EXIST
+ "Queue %S does not exist on server %S.\n"
+ IDR_TIME_OUT_EXPECTED
+ "Timeout value (0-1000) expected.\n"
+ IDR_LPT_NUMBER_EXPECTED
+ "Local printer number (1, 2, or 3) expected.\n"
+ IDR_FORM_EXPECTED
+ "Form number expected.\n"
+ IDR_COPIES_EXPECTED
+ "Number of copies (1-255) expected.\n"
+ IDR_TAB_SIZE_EXPECTED
+ "Tab size expected.\n"
+ IDR_JOB_NOT_FOUND
+ "%S is not a valid PrintCon job definition.\n"
+ IDR_FILE_CAPTURE_UNSUPPORTED
+ "File Capture is unsupported.\n"
+ IDR_DISABLED
+ "Disabled"
+ IDR_ENABLED
+ "Enabled"
+ IDR_YES
+ "Yes"
+ IDR_NO
+ "No";
+ IDR_SECONDS
+ "%d seconds";
+ IDR_CONVERT_TO_SPACE
+ "Converted to %d spaces";
+ IDR_NO_CONVERSION
+ "No conversion";
+ IDR_NOTIFY_USER
+ "User will be notified after the files are printed.";
+ IDR_NOT_NOTIFY_USER
+ "User will not be notified after the files are printed.";
+ IDR_NONE
+ "(None)";
+ IDR_CONNECTION_REFUSED
+ "Server refused the login; too many sessions.\n";
+ IDR_LASTLOGIN_PM
+ "Last login occurred at: %d-%02d-%02d %d:%02d:%02d pm.\n";
+ IDR_LASTLOGIN_AM
+ "Last login occurred at: %d-%02d-%02d %d:%02d:%02d am.\n";
+ IDR_ALL_LOCAL_DRIVES
+ "Drives %S map to a local disk.\n";
+ IDR_CHANGE_CONTEXT_ERROR
+ "The context you want to change to does not exist.\nYou tried to change to:\n[%S]\nYour context will be left unchanged.\n";
+ IDR_GET_CONTEXT_ERROR
+ "Error accessing the current context.\n";
+ IDR_DISPLAY_CONTEXT
+ "Your context has been changed to: %S\n";
+ IDR_LPT_STATUS_NDS
+ "\n LPT%d: Capturing data to print queue %S.\n %s\n Capture Defaults:%-15sAutomatic Endcap:%s\n Banner :%-24SForm Feed :%s\n Copies :%-24dTabs :%s\n Form :%-24dTimeout Count :%s\n"
+ IDR_LPT_STATUS_NO_BANNER_NDS
+ "\n LPT%d: Capturing data to print queue %S.\n %s\n Capture Defaults:%-15sAutomatic Endcap:%s\n Banner :%-24sForm Feed :%s\n Copies :%-24dTabs :%s\n Form :%-24dTimeout Count :%s\n"
+ IDR_NO_QUEUE
+ "No printer queue was specified\n";
+ IDR_LASTLOGIN
+ "Last login occurred at: %s %s.\n";
+ IDR_TREE_OPEN_FAILED
+ "Cannot open NDS tree\n";
+ IDR_NDS_CONTEXT_INVALID
+ "NDS context is invalid\n";
+ IDR_NDS_USERNAME_FAILED
+ "NDS user name could not be accessed\n";
+ IDR_QUERY_INFO_FAILED
+ "NetWare information query failed\n";
+ IDR_NDSQUEUE_NOT_EXIST
+ "Queue %S does not exist.\n"
+ IDR_NDSSUCCESS_QUEUE
+ "Device LPT%d: re-routed to queue %S.\n"
+ IDR_CAPTURE_FAILED
+ "Capture of queue %S failed.\n"
+ IDR_CURRENT_TREE
+ "Your current tree is: %s\n"
+ IDR_CURRENT_SERVER
+ "You are attached to server %S.\n"
+ IDR_CURRENT_CONTEXT
+ "Your current context is %S\n"
+ IDR_AUTHENTICATING_SERVER
+ "Authenticating to server %S.\n"
+ IDR_NO_END_QUOTE
+ "Script Error: The line contains no end quote.\n"
+END
diff --git a/private/nw/nwscript/parspath.c b/private/nw/nwscript/parspath.c
new file mode 100644
index 000000000..77f3a250c
--- /dev/null
+++ b/private/nw/nwscript/parspath.c
@@ -0,0 +1,341 @@
+
+/*************************************************************************
+*
+* PARSPATH.C
+*
+* NetWare parsing routines, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\PARSPATH.C $
+*
+* Rev 1.3 22 Jan 1996 16:48:38 terryt
+* Add automatic attach query during map
+*
+* Rev 1.2 22 Dec 1995 14:26:16 terryt
+* Add Microsoft headers
+*
+* Rev 1.1 22 Dec 1995 11:08:50 terryt
+* Fixes
+*
+* Rev 1.0 15 Nov 1995 18:07:48 terryt
+* Initial revision.
+*
+* Rev 1.1 25 Aug 1995 16:23:34 terryt
+* Capture support
+*
+* Rev 1.0 15 May 1995 19:11:00 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+/*++
+
+Copyright (c) 1994 Micro Computer Systems, Inc.
+
+Module Name:
+
+ nwlibs\parspath.c
+
+Abstract:
+
+ Directory APIs.
+
+Author:
+
+ Shawn Walker (v-swalk) 10-10-1994
+
+Revision History:
+
+--*/
+#include "common.h"
+#include <ctype.h>
+#include <direct.h>
+#include "inc\nwlibs.h"
+
+
+/*++
+*******************************************************************
+
+ ParsePath
+
+Routine Description:
+
+ Parse the path string.
+
+Arguments:
+
+ pPath = The pointer to the path to parse.
+ pServerName = The pointer to return the server name.
+ pVolumeName = The pointer to return the volume name.
+ pDirPath = The pointer to return the directory path.
+
+Return Value:
+
+ 0x0000 SUCCESSFUL
+ 0x000F INVALID_DRIVE
+ 0x8800 Unknown error
+
+*******************************************************************
+--*/
+unsigned int
+ParsePath(
+ unsigned char *pPath,
+ unsigned char *pServerName, //OPTIONAL
+ unsigned char *pVolumeName, //OPTIONAL
+ unsigned char *pDirPath //OPTIONAL
+ )
+{
+ unsigned char *p, *p2;
+ unsigned int Result;
+ unsigned int Remote;
+ unsigned int NcpError = 0;
+ unsigned char DriveNumber = (unsigned char)-1;
+ unsigned char CurrentPath[64];
+ unsigned char RootPath[NCP_MAX_PATH_LENGTH];
+ unsigned char ServerName[NCP_MAX_PATH_LENGTH];
+ unsigned char *pRootDir;
+ unsigned char NetWarePath[NCP_MAX_PATH_LENGTH];
+ unsigned char VolumeName[NCP_VOLUME_LENGTH];
+ unsigned int LocalDriveForce = FALSE;
+
+ RootPath[0] = 0;
+ VolumeName[0] = 0;
+ ServerName[0] = 0;
+
+ if ( pServerName )
+ *pServerName = '\0';
+
+ /** See if there is a volume on the path **/
+
+ p = pPath;
+ while (*p != ':' && *p) {
+ p++;
+ }
+
+ if (*p == ':') {
+ *p = 0;
+
+ /**
+ Check to see if this is a drive letter. The volume must
+ be 2 characters or more.
+ **/
+
+ if ((p - pPath) == 1) {
+
+ /** Make sure it is a valid alpha char **/
+
+ if (!isalpha((int) *pPath)) {
+ return 0x000F;
+ }
+
+ *pPath = (unsigned char) toupper((int) *pPath);
+
+ /** Make it a drive number **/
+
+ DriveNumber = (unsigned char) (*pPath - 'A');
+ GetDriveStatus ((unsigned short)(DriveNumber+1),
+ NETWARE_FORMAT_SERVER_VOLUME,
+ NULL,
+ NULL,
+ RootPath,
+ NULL,
+ NULL);
+ pRootDir = strchr (RootPath, ':');
+ if (pRootDir)
+ {
+ /*
+ * Setup the pServerName here
+ */
+
+ pRootDir[0] = '\0';
+ p2 = RootPath;
+ while (*p2)
+ {
+ if (*p2 == '\\' || *p2 == '/')
+ {
+ *p2++ = 0;
+ strcpy(ServerName, RootPath);
+ if (pServerName) {
+ strcpy(pServerName, RootPath);
+ }
+ break;
+ }
+ p2++;
+ }
+ strcpy (RootPath, pRootDir+1);
+ }
+ else
+ RootPath[0] = 0;
+ }
+ else {
+
+ DriveNumber = 0;
+ LocalDriveForce = TRUE;
+
+ /**
+ If there is a server name, save the server name
+ and set the error code to 0x880F but still parse
+ the path. This just means that there is no connection
+ for this server. Even if we do have one.
+ **/
+
+ p2 = pPath;
+ while (*p2) {
+ if (*p2 == '\\' || *p2 == '/') {
+ *p2++ = 0;
+
+ strcpy(ServerName, pPath);
+ if (pServerName) {
+ strcpy(pServerName, pPath);
+ }
+ pPath = p2;
+
+ NcpError = 0x880F;
+ break;
+ }
+ p2++;
+ }
+
+ if (NcpError == 0x880F) {
+ /**
+ Do any attach processing.
+ **/
+
+ NcpError = DoAttachProcessing( ServerName );
+
+ }
+
+ strcpy(VolumeName, pPath);
+ }
+
+ /** Get the directory **/
+
+ p++;
+ pPath = p;
+ }
+
+ /**
+ If we did not get the drive letter of volume name
+ from above, then get the current drive we are on.
+ **/
+
+ if (DriveNumber == (unsigned char) -1) {
+ DriveNumber = _getdrive();
+ }
+
+ /*
+ * Use the PREFERRED_SERVER for 3X logins if no server name
+ * was specified.
+ */
+ if (pServerName && !fNDS && !pServerName[0] ) {
+ strcpy( pServerName, PREFERRED_SERVER );
+ }
+
+ if (pVolumeName) {
+
+ /**
+ Check if the drive is remote, if so, then go get the path
+ from the server.
+ **/
+ if ( LocalDriveForce ) {
+ Result = 0;
+ Remote = 0;
+ }
+ else {
+ Result = IsDriveRemote(DriveNumber, &Remote);
+
+ }
+
+ if (NcpError != 0x880F && !VolumeName[0] && (Result || !Remote)) {
+ pVolumeName[0] = (unsigned char) (DriveNumber + 'A');
+ pVolumeName[1] = 0;
+ }
+ else {
+ if (VolumeName[0]) {
+ strcpy(pVolumeName, VolumeName);
+ }
+ else {
+ Result = NTGetNWDrivePath( DriveNumber, NULL, NetWarePath );
+ if (Result) {
+ return Result;
+ }
+
+ p = NetWarePath;
+ while (*p != ':' && *p) {
+ p++;
+ }
+
+ if (*p == ':') {
+ *p = 0;
+ }
+ strcpy(pVolumeName, NetWarePath);
+ }
+ }
+ }
+
+ if (pDirPath) {
+
+ memset(CurrentPath, 0, sizeof(CurrentPath));
+
+ if (VolumeName[0]) {
+ strcpy(pDirPath, pPath);
+ }
+ else {
+ Result = NTGetCurrentDirectory(DriveNumber, CurrentPath);
+ if (Result) {
+ CurrentPath[0] = 0;
+ }
+ else {
+ /*
+ * Skip the drive letter
+ */
+ if ( CurrentPath[0] ) {
+ int i;
+ for ( i = 0; ;i++ ) {
+ CurrentPath[i] = CurrentPath[i+3];
+ if ( !CurrentPath[i] )
+ break;
+ }
+ }
+ }
+
+ if (CurrentPath[0] == 0) {
+ if ( (*pPath == '\\') || ( *pPath == '/' ) ) {
+ sprintf(pDirPath, "%s%s", RootPath, pPath);
+ }
+ else if ( !(*pPath) ) {
+ sprintf(pDirPath, "%s", RootPath);
+ }
+ else {
+ sprintf(pDirPath, "%s\\%s", RootPath, pPath);
+ }
+ }
+ else {
+ if (*pPath) {
+ if ( (*pPath == '\\') || ( *pPath == '/' ) ) {
+ strcpy (pDirPath, RootPath);
+ if (pPath[1]) {
+ strcat(pDirPath, pPath);
+ }
+ }
+ else {
+ sprintf(pDirPath, "%s\\%s\\%s", RootPath, CurrentPath, pPath);
+ }
+ }
+ else {
+ sprintf(pDirPath, "%s\\%s", RootPath, CurrentPath);
+ }
+ }
+ }
+
+ /** Convert the / in the path to \ **/
+ for (p = pDirPath; ( p && ( *p != 0 ) ) ; p++)
+ {
+ if (*p == '/')
+ *p = '\\';
+ }
+ }
+
+ return NcpError;
+}
diff --git a/private/nw/nwscript/ps40db.c b/private/nw/nwscript/ps40db.c
new file mode 100644
index 000000000..9eae6aa09
--- /dev/null
+++ b/private/nw/nwscript/ps40db.c
@@ -0,0 +1,597 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ psndsdb.c
+
+Abstract:
+
+ Read the Print Configuration Attributes
+
+ $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\PS40DB.C $
+*
+* Rev 1.4 10 Apr 1996 14:23:28 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.4 12 Mar 1996 19:55:22 terryt
+* Relative NDS names and merge
+*
+* Rev 1.3 04 Jan 1996 18:57:36 terryt
+* Bug fixes reported by MS
+*
+* Rev 1.2 22 Dec 1995 14:26:22 terryt
+* Add Microsoft headers
+*
+* Rev 1.1 20 Nov 1995 15:09:46 terryt
+* Context and capture changes
+*
+* Rev 1.0 15 Nov 1995 18:07:52 terryt
+* Initial revision.
+
+--*/
+#include "common.h"
+
+extern DWORD SwapLong(DWORD number);
+extern char *TYPED_USER_NAME;
+
+unsigned int
+PS40GetJobName(
+ unsigned int NDSCaptureFlag,
+ unsigned short SearchFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord,
+ unsigned char GetDefault
+ );
+
+#include <pshpack1.h>
+#define NWPS_JOB_NAME_SIZE 32 /* 31 bytes and a '\0' */
+#define NWPS_FORM_NAME_SIZE 12 /* 12 bytes and a '\0' */
+#define NWPS_BANNER_NAME_SIZE 12 /* 12 bytes and a '\0' */
+#define NWPS_BANNER_FILE_SIZE 12 /* 12 bytes and a '\0' */
+#define NWPS_DEVI_NAME_SIZE 32 /* 32 bytes and a '\0' */
+#define NWPS_MODE_NAME_SIZE 32 /* 32 bytes and a '\0' */
+#define NWPS_BIND_NAME_SIZE 48
+#define NWPS_MAX_NAME_SIZE 514
+/*
+// NWPS_Job_Old_Db_Hdr is the first record in the 4.0 PrnConDB database.
+// It contains the following information about the database:
+// The version number,
+// the number of NWPS_Job_Rec records in PrnConDB,
+// the name of the default print job configuration and
+// the name of the job record owner.
+*/
+typedef struct {
+ char text[ 76 ]; /* Printcon database. Version 4.0 */
+ char DefaultJobName[ 32 ]; /* Name of default Job */
+ char Owner[ 256 ]; /* owner of the job record */
+ WORD NumberOfRecords; /* # of NWPS_Job_Rec's in PrnConDB */
+ WORD NumberOfBlocks; /* # of 50-(NWPS_Job_Name_Rec) blocks */
+ BYTE MajorVersion; /* 4 */
+ BYTE MinorVersion; /* 0 */
+} PRINTCON_40_HEADER;
+
+#define PRINTCON_40_HEADER_SIZE sizeof(PRINTCON_40_HEADER)
+
+/*
+// NWPS_Job_41_Db_Hdr is the first record in the 4.1 PrnConDB database.
+// It contains the following information about the database:
+// The version number,
+// the number of NWPS_Job_Rec records in PrnConDB,
+// the name of the default print job configuration and
+// the name of the job record owner IN UNICODE.
+*/
+typedef struct {
+ char text[ 76 ]; /* Printcon database. Version 4.1 */
+ char DefaultJobName[ 32 ]; /* Name of default Job */
+ char unused[ 256 ]; /* no longer used. */
+ WORD NumberOfRecords; /* # of NWPS_Job_Rec's in PrnConDB */
+ WORD NumberOfBlocks; /* # of 50-(NWPS_Job_Name_Rec) blocks */
+ BYTE MajorVersion; /* 4 */
+ BYTE MinorVersion; /* 1 unicode defaultPJOwner etc. */
+ WORD Owner[ 256 ]; /* owner of the default job record */
+} PRINTCON_41_HEADER;
+
+#define PRINTCON_41_HEADER_SIZE sizeof(PRINTCON_41_HEADER)
+
+/*
+// NWPS_Job_Name_Rec is the type of record found in the
+// second section of the PrnConDB database. Each one of
+// these records contains the name of each NWPS_Job_Rec
+// and a pointer to their location in the third section of
+// the database. There is space set aside in this second
+// section for fifty NWPS_Job_Name_Rec records; if this
+// limit is exceeded then another fifty-record block following
+// the first one is allocated after the third section of the
+// database is moved down to make room for the expansion.
+*/
+typedef struct {
+ char JobName[ NWPS_JOB_NAME_SIZE ]; /* 1 - 31 chars long + 0 */
+ long JobRecordOffset; /* Offset of the record
+ // (from the beginning
+ // of the 3rd section for 4.0
+ // databases and from the start
+ // of the file for pre-4.0)
+ */
+} JOB_NAME_AREA;
+
+#define JOB_NAME_AREA_SIZE sizeof(JOB_NAME_AREA)
+
+typedef struct {
+ union {
+ struct {
+ DWORD DataType : 1; /* 0=Byte stream 1 = Text */
+ DWORD FormFeed : 1; /* 0 = FF; 1 = suppress FF */
+ DWORD NotifyWhenDone : 1; /* 0 = no, 1 = yes */
+ DWORD BannerFlag : 1; /* 0 = no, 1 = yes */
+ DWORD AutoEndCap : 1; /* 0 = no, 1 = yes */
+ DWORD TimeOutFlag: 1; /* 0 = no, 1 = yes */
+ DWORD SystemType : 3; /* 0 = bindery 1 = NDS */
+ DWORD Destination: 3; /* 0 = queue 1 = printer */
+ DWORD unknown : 20;
+ };
+ DWORD PrintJobFlags;
+ };
+
+ WORD NumberOfCopies; /* 1 - 65,000 */
+ WORD TimeoutCount; /* 1 - 1,000 */
+ BYTE TabSize; /* 1 - 18 */
+ BYTE LocalPrinter; /* 0=Lpt1, 1=Lpt2, 2=Lpt3 etc. */
+ char FormName[ NWPS_FORM_NAME_SIZE + 2 ]; /* 1-12 chars */
+ char Name[ NWPS_BANNER_NAME_SIZE + 2 ]; /* 1-12 chars */
+ char BannerName[ NWPS_BANNER_FILE_SIZE + 2 ]; /* 1-12 chars */
+ char Device[ NWPS_DEVI_NAME_SIZE + 2 ]; /* 1-32 chars */
+ char Mode[ NWPS_MODE_NAME_SIZE + 2 ]; /* 1-32 chars */
+ union {
+ struct {
+ /* pad structures on even boundries */
+ char Server[ NWPS_BIND_NAME_SIZE + 2 ]; /* 2-48 chars */
+ char QueueName[ NWPS_BIND_NAME_SIZE + 2 ]; /* 1-48 chars */
+ char PrintServer[ NWPS_BIND_NAME_SIZE + 2 ]; /* 1-48 chars */
+ } NonDS;
+ char DSObjectName[ NWPS_MAX_NAME_SIZE ];
+ } u;
+ BYTE reserved[390]; /* Adds up to 1024 total (was 1026) */
+} JOB_RECORD_AREA;
+
+#define JOB_RECORD_AREA_SIZE sizeof(JOB_RECORD_AREA)
+
+
+#include <poppack.h>
+
+
+
+/*++
+*******************************************************************
+
+ PS40JobGetDefault
+
+Routine Description:
+
+ Get the default print job configuration from 40.
+
+Arguments:
+ NDSCaptureFlag
+ SearchFlag =
+ pOwner =
+ pJobName = A pointer to return the default job configuration name.
+ pJobRecord = A pointer to return the default job configuration.
+
+Return Value:
+
+ SUCCESSFUL 0x0000
+ PS_ERR_BAD_VERSION 0x7770
+ PS_ERR_GETTING_DEFAULT 0x7773
+ PS_ERR_OPENING_DB 0x7774
+ PS_ERR_READING_DB 0x7775
+ PS_ERR_READING_RECORD 0x7776
+ PS_ERR_INTERNAL_ERROR 0x7779
+ PS_ERR_NO_DEFAULT_SPECIFIED 0x777B
+ INVALID_CONNECTION 0x8801
+
+*******************************************************************
+--*/
+unsigned int
+PS40JobGetDefault(
+ unsigned int NDSCaptureFlag,
+ unsigned short SearchFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord
+ )
+{
+ return PS40GetJobName(
+ NDSCaptureFlag,
+ SearchFlag,
+ pOwner,
+ pJobName,
+ pJobRecord,
+ TRUE);
+}
+
+
+/*++
+*******************************************************************
+
+ PS40JobRead
+
+Routine Description:
+
+ Get the print job configuration from 40.
+
+Arguments:
+
+ NDSCaptureFlag =
+ pOwner =
+ pJobName = A pointer to return the default job configuration name.
+ pJobRecord = A pointer to return the default job configuration.
+
+Return Value:
+
+ SUCCESSFUL 0x0000
+ PS_ERR_BAD_VERSION 0x7770
+ PS_ERR_GETTING_DEFAULT 0x7773
+ PS_ERR_OPENING_DB 0x7774
+ PS_ERR_READING_DB 0x7775
+ PS_ERR_READING_RECORD 0x7776
+ PS_ERR_INTERNAL_ERROR 0x7779
+ PS_ERR_NO_DEFAULT_SPECIFIED 0x777B
+ INVALID_CONNECTION 0x8801
+
+*******************************************************************
+--*/
+unsigned int
+PS40JobRead(
+ unsigned int NDSCaptureFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord
+ )
+{
+ return PS40GetJobName(
+ NDSCaptureFlag,
+ 0,
+ pOwner,
+ pJobName,
+ pJobRecord,
+ FALSE);
+}
+
+
+/*++
+*******************************************************************
+
+ PS40GetJobName
+
+Routine Description:
+
+ Common routine to get the print job configuration from 40.
+
+Arguments:
+ NDSCaptureFlag =
+ SearchFlag =
+ pOwner =
+ pJobName = A pointer to return the default job configuration name.
+ pJobRecord = A pointer to return the default job configuration.
+ GetDefault = TRUE = get the default job name, FALSE = Don't get
+ the default job name.
+
+Return Value:
+
+ SUCCESSFUL 0x0000
+ PS_ERR_BAD_VERSION 0x7770
+ PS_ERR_GETTING_DEFAULT 0x7773
+ PS_ERR_OPENING_DB 0x7774
+ PS_ERR_READING_DB 0x7775
+ PS_ERR_READING_RECORD 0x7776
+ PS_ERR_INTERNAL_ERROR 0x7779
+ PS_ERR_NO_DEFAULT_SPECIFIED 0x777B
+ INVALID_CONNECTION 0x8801
+
+*******************************************************************
+--*/
+unsigned int
+PS40GetJobName(
+ unsigned int NDSCaptureFlag,
+ unsigned short SearchFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord,
+ unsigned char GetDefault
+ )
+{
+ unsigned char *pSearchJobName;
+ unsigned long ObjectId;
+ HANDLE stream = NULL;
+ unsigned int Count;
+ unsigned int Bytes;
+ unsigned int RetCode = 0;
+ unsigned int ConnectionNumber;
+ JOB_NAME_AREA JobNameArea;
+ JOB_RECORD_AREA JobRecord;
+ PRINTCON_40_HEADER PrintConHeader;
+ unsigned int Version40 = FALSE;
+ unsigned int ConnectionHandle;
+ unsigned char MailDirPath[NCP_MAX_PATH_LENGTH];
+ unsigned char TempJobName[32];
+ PBYTE JobContext = NULL;
+ unsigned FileSize;
+
+ // BUGBUG Printer names can be used instead of queues
+ // Must lookup "default print queue" if NT doesn't
+
+ if ( NDSCaptureFlag ) {
+
+ if ( !GetDefault ) {
+ JobContext = strchr( pJobName, ':' );
+ if ( JobContext ) {
+ *JobContext = '\0';
+ strncpy( TempJobName, pJobName, 32 );
+ *JobContext++ = ':';
+ pJobName = TempJobName;
+ }
+ }
+
+ if ( JobContext ) {
+ if (NDSfopenStream ( JobContext, "Print Job Configuration", &stream,
+ &FileSize )) {
+ RetCode = PS_ERR_OPENING_DB;
+ goto CommonExit;
+ }
+ }
+ else {
+ if (NDSfopenStream ( TYPED_USER_NAME, "Print Job Configuration",
+ &stream, &FileSize)) {
+ PBYTE p;
+
+ for ( p = TYPED_USER_NAME; p ; p = strchr ( p, '.' ) )
+ {
+ p++;
+
+ if ( *p == 'O' && *(p+1) == 'U' && *(p+2) == '=' )
+ break;
+
+ if ( *p == 'O' && *(p+1) == '=' )
+ break;
+ }
+ if (NDSfopenStream ( p, "Print Job Configuration", &stream,
+ &FileSize)) {
+ RetCode = PS_ERR_OPENING_DB;
+ goto CommonExit;
+ }
+ }
+ }
+ }
+ else {
+
+ if (!CGetDefaultConnectionID (&ConnectionHandle)) {
+ RetCode = PS_ERR_OPENING_DB;
+ goto CommonExit;
+ }
+
+ RetCode = GetConnectionNumber(ConnectionHandle, &ConnectionNumber);
+ if (RetCode) {
+ goto CommonExit;
+ }
+
+ RetCode = GetBinderyObjectID (ConnectionHandle, LOGIN_NAME,
+ OT_USER, &ObjectId);
+ if (RetCode) {
+ goto CommonExit;
+ }
+
+ /** Build the path to open the file **/
+
+ sprintf(MailDirPath, "SYS:MAIL/%lX/PRINTJOB.DAT", SwapLong(ObjectId));
+ stream = CreateFileA( NTNWtoUNCFormat( MailDirPath ),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+ if (stream == INVALID_HANDLE_VALUE) {
+
+ sprintf(MailDirPath, "SYS:PUBLIC/PRINTJOB.DAT");
+
+ stream = CreateFileA( NTNWtoUNCFormat(MailDirPath),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+
+ if (stream == INVALID_HANDLE_VALUE) {
+ RetCode = PS_ERR_OPENING_DB;
+ goto CommonExit;
+ }
+ }
+ }
+
+ if ( !ReadFile( stream, (PBYTE) &PrintConHeader, PRINTCON_40_HEADER_SIZE, &Bytes, NULL ) ) {
+ RetCode = PS_ERR_INTERNAL_ERROR;
+ goto CommonExit;
+ }
+
+ if (Bytes < PRINTCON_40_HEADER_SIZE) {
+ if ( !( NDSCaptureFlag && Bytes) ) { // BUGBUG
+ RetCode = PS_ERR_INTERNAL_ERROR;
+ goto CommonExit;
+ }
+ }
+
+ /** Check the version number **/
+
+ if ( PrintConHeader.MajorVersion != 4 ) {
+ RetCode = PS_ERR_BAD_VERSION;
+ goto CommonExit;
+ }
+
+ if ( PrintConHeader.MinorVersion == 0 ) {
+ Version40 = TRUE;
+ }
+
+ /** Get the name we are looking for **/
+
+ if (GetDefault) {
+ if (PrintConHeader.DefaultJobName[0] == 0) {
+ RetCode = PS_ERR_GETTING_DEFAULT;
+ goto CommonExit;
+ }
+ pSearchJobName = PrintConHeader.DefaultJobName;
+ }
+ else {
+ pSearchJobName = pJobName;
+ }
+
+ if ( !Version40 ) {
+ SetFilePointer( stream, PRINTCON_41_HEADER_SIZE, NULL, FILE_BEGIN );
+ }
+
+ Count = 0;
+
+ /** Go through all of the job entry to look for the name **/
+
+ while (Count < PrintConHeader.NumberOfRecords) {
+ if ( !ReadFile( stream, (PBYTE) &JobNameArea, JOB_NAME_AREA_SIZE, &Bytes, NULL) ) {
+ RetCode = PS_ERR_INTERNAL_ERROR;
+ goto CommonExit;
+ }
+
+ if (Bytes < JOB_NAME_AREA_SIZE) {
+ if ( !( NDSCaptureFlag && Bytes) ) { // BUGBUG
+ RetCode = PS_ERR_INTERNAL_ERROR;
+ goto CommonExit;
+ }
+ }
+ Count++;
+
+
+ /** Skip the entry with a null job name **/
+
+ if (JobNameArea.JobName[0] == 0) {
+ continue;
+ }
+
+ /** Is this the job name we are looking for? **/
+
+ if (!_strcmpi(pSearchJobName, JobNameArea.JobName)) {
+ break;
+ }
+ }
+
+ /** See if we found the job name **/
+
+ if (Count > PrintConHeader.NumberOfRecords) {
+ if (GetDefault) {
+ RetCode = PS_ERR_GETTING_DEFAULT;
+ }
+ else {
+ RetCode = PS_ERR_READING_RECORD;
+ }
+ goto CommonExit;
+ }
+
+ /*
+ * The Job offset starts at the beginning of the third section.
+ * The third section starts after the Header and after the
+ * 50 record blocks.
+ */
+ if ( Version40 ) {
+ SetFilePointer( stream,
+ PRINTCON_40_HEADER_SIZE +
+ ( PrintConHeader.NumberOfBlocks * 50) * JOB_NAME_AREA_SIZE +
+ JobNameArea.JobRecordOffset,
+ NULL,
+ FILE_BEGIN );
+ }
+ else {
+ SetFilePointer( stream,
+ PRINTCON_41_HEADER_SIZE +
+ ( PrintConHeader.NumberOfBlocks * 50) * JOB_NAME_AREA_SIZE +
+ JobNameArea.JobRecordOffset,
+ NULL,
+ FILE_BEGIN );
+ }
+
+ memset((PBYTE)&JobRecord, 0, sizeof(JobRecord));
+
+ if ( !ReadFile( stream, (PBYTE) &JobRecord, JOB_RECORD_AREA_SIZE, &Bytes, NULL) ) {
+ RetCode = PS_ERR_READING_RECORD;
+ goto CommonExit;
+ }
+
+ if (Bytes < JOB_RECORD_AREA_SIZE) {
+ if ( !( NDSCaptureFlag && Bytes) ) { // BUGBUG
+ RetCode = PS_ERR_READING_RECORD;
+ goto CommonExit;
+ }
+ }
+
+ memset(pJobRecord, 0, PS_JOB_RECORD_SIZE);
+
+ if (JobRecord.NotifyWhenDone) {
+ pJobRecord->PrintJobFlag |= PS_JOB_NOTIFY;
+ }
+ if (JobRecord.BannerFlag) {
+ pJobRecord->PrintJobFlag |= PS_JOB_PRINT_BANNER;
+ }
+ if (JobRecord.DataType) {
+ pJobRecord->PrintJobFlag |= PS_JOB_EXPAND_TABS;
+ }
+ if (JobRecord.FormFeed) {
+ pJobRecord->PrintJobFlag |= PS_JOB_NO_FORMFEED;
+ }
+ if (JobRecord.AutoEndCap) {
+ pJobRecord->PrintJobFlag |= PS_JOB_AUTO_END;
+ }
+ if (JobRecord.TimeoutCount) {
+ pJobRecord->PrintJobFlag |= PS_JOB_TIMEOUT;
+ }
+ if (JobRecord.Destination) {
+ pJobRecord->PrintJobFlag |= PS_JOB_DS_PRINTER;
+ }
+ if ( JobRecord.SystemType ) {
+ pJobRecord->PrintJobFlag |= PS_JOB_ENV_DS;
+ }
+
+ pJobRecord->Copies = JobRecord.NumberOfCopies;
+ pJobRecord->TabSize = JobRecord.TabSize;
+ pJobRecord->TimeOutCount = JobRecord.TimeoutCount;
+ pJobRecord->LocalPrinter = JobRecord.LocalPrinter;
+
+ strcpy(pJobRecord->Mode, JobRecord.Mode);
+ strcpy(pJobRecord->Device, JobRecord.Device);
+ strcpy(pJobRecord->FormName, JobRecord.FormName);
+ strcpy(pJobRecord->BannerName, JobRecord.BannerName);
+
+ if ( JobRecord.SystemType ) {
+ ConvertUnicodeToAscii( JobRecord.u.DSObjectName );
+ strcpy(pJobRecord->u.DSObjectName, JobRecord.u.DSObjectName);
+ }
+ else {
+ strcpy(pJobRecord->u.NonDS.PrintQueue, JobRecord.u.NonDS.QueueName);
+ strcpy(pJobRecord->u.NonDS.FileServer, JobRecord.u.NonDS.Server);
+ }
+
+ if (GetDefault && pJobName) {
+ strcpy(pJobName, JobNameArea.JobName);
+ }
+
+ if (pOwner) {
+ *pOwner = 0;
+ }
+
+CommonExit:
+ if (stream != NULL) {
+ if ( NDSCaptureFlag )
+ CloseHandle( stream );
+ else
+ fclose( stream );
+ }
+
+ return RetCode;
+}
diff --git a/private/nw/nwscript/psdb.c b/private/nw/nwscript/psdb.c
new file mode 100644
index 000000000..713c1c4c4
--- /dev/null
+++ b/private/nw/nwscript/psdb.c
@@ -0,0 +1,396 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ nwlibs\psdb.c
+
+Abstract:
+
+ Read the Print Con database file APIs.
+
+Author:
+
+ Shawn Walker (v-swalk) 12-12-1994
+
+Revision History:
+
+--*/
+#include "common.h"
+
+extern DWORD SwapLong(DWORD number);
+
+unsigned int
+PSGetJobName(
+ unsigned int ConnectionHandle,
+ unsigned short SearchFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord,
+ unsigned char GetDefault
+ );
+
+#define MAX_JOB_NAME_ENTRY 37
+
+#define O_RDONLY 0x0000 /* open for reading only */
+#define O_WRONLY 0x0001 /* open for writing only */
+#define O_RDWR 0x0002 /* open for reading and writing */
+#define O_APPEND 0x0008 /* writes done at eof */
+#define O_CREAT 0x0100 /* create and open file */
+#define O_TRUNC 0x0200 /* open and truncate */
+#define O_EXCL 0x0400 /* open only if file doesn't already exist */
+#define O_TEXT 0x4000 /* file mode is text (translated) */
+#define O_BINARY 0x8000 /* file mode is binary (untranslated) */
+
+#define S_IEXEC 0000100 /* execute/search permission, owner */
+#define S_IWRITE 0000200 /* write permission, owner */
+#define S_IREAD 0000400 /* read permission, owner */
+#define S_IFCHR 0020000 /* character special */
+#define S_IFDIR 0040000 /* directory */
+#define S_IFREG 0100000 /* regular */
+#define S_IFMT 0170000 /* file type mask */
+
+#include <pshpack1.h>
+typedef struct _PRINTCON_HEADER {
+ unsigned char Text[115];
+ unsigned char MajorVersion;
+ unsigned char MinorVersion1;
+ unsigned char MinorVersion2;
+ unsigned char DefaultJobName[32];
+} PRINTCON_HEADER, *PPRINTCON_HEADER;
+
+#define PRINTCON_HEADER_SIZE sizeof(PRINTCON_HEADER)
+
+typedef struct _JOB_NAME_AREA {
+ unsigned char JobName[32];
+ unsigned long JobRecordOffset;
+} JOB_NAME_AREA, *PJOB_NAME_AREA;
+
+#define JOB_NAME_AREA_SIZE sizeof(JOB_NAME_AREA)
+
+typedef struct _JOB_RECORD_AREA {
+ unsigned char ServerName[NCP_BINDERY_OBJECT_NAME_LENGTH];
+ unsigned char QueueName[NCP_BINDERY_OBJECT_NAME_LENGTH];
+ unsigned char TabSize;
+ unsigned short NumberOfCopies;
+ unsigned char FormName[40];
+ unsigned char NotifyWhenDone; //0=No, 1=Yes
+ unsigned long PrintServerID;
+ unsigned char Name[13];
+ unsigned char BannerName[13];
+ unsigned char Device[33];
+ unsigned char Mode[33];
+ unsigned char BannerFlag; //0=No Banner, 1=Banner
+ unsigned char DataType; //1=Byte,0=Stream
+ unsigned char FormFeed; //0=Don't Suppress FF, 1=Suppress FF
+ unsigned short TimeoutCount;
+ unsigned char LocalPrinter; //1=LPT1, 2=LPT2, 3=LPT3
+ unsigned char AutoEndCap; //0=Don't Auto EndCap, 1=Do Auto EndCap
+} JOB_RECORD_AREA, *PJOB_RECORD_AREA;
+#include <poppack.h>
+
+#define JOB_RECORD_AREA_SIZE sizeof(JOB_RECORD_AREA)
+
+
+/*++
+*******************************************************************
+
+ PSJobGetDefault
+
+Routine Description:
+
+ Get the default print job configuration from the printcon.dat
+ file.
+
+Arguments:
+
+ ConnectionHandle = The connection handle to use.
+ SearchFlag =
+ pOwner =
+ pJobName = A pointer to return the default job configuration name.
+ pJobRecord = A pointer to return the default job configuration.
+
+Return Value:
+
+ SUCCESSFUL 0x0000
+ PS_ERR_BAD_VERSION 0x7770
+ PS_ERR_GETTING_DEFAULT 0x7773
+ PS_ERR_OPENING_DB 0x7774
+ PS_ERR_READING_DB 0x7775
+ PS_ERR_READING_RECORD 0x7776
+ PS_ERR_INTERNAL_ERROR 0x7779
+ PS_ERR_NO_DEFAULT_SPECIFIED 0x777B
+ INVALID_CONNECTION 0x8801
+
+*******************************************************************
+--*/
+unsigned int
+PSJobGetDefault(
+ unsigned int ConnectionHandle,
+ unsigned short SearchFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord
+ )
+{
+ return PSGetJobName(
+ ConnectionHandle,
+ SearchFlag,
+ pOwner,
+ pJobName,
+ pJobRecord,
+ TRUE);
+}
+
+
+/*++
+*******************************************************************
+
+ PSJobRead
+
+Routine Description:
+
+ Get the print job configuration from the printcon.dat file.
+
+Arguments:
+
+ ConnectionHandle = The connection handle to use.
+ pOwner =
+ pJobName = A pointer to return the default job configuration name.
+ pJobRecord = A pointer to return the default job configuration.
+
+Return Value:
+
+ SUCCESSFUL 0x0000
+ PS_ERR_BAD_VERSION 0x7770
+ PS_ERR_GETTING_DEFAULT 0x7773
+ PS_ERR_OPENING_DB 0x7774
+ PS_ERR_READING_DB 0x7775
+ PS_ERR_READING_RECORD 0x7776
+ PS_ERR_INTERNAL_ERROR 0x7779
+ PS_ERR_NO_DEFAULT_SPECIFIED 0x777B
+ INVALID_CONNECTION 0x8801
+
+*******************************************************************
+--*/
+unsigned int
+PSJobRead(
+ unsigned int ConnectionHandle,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord
+ )
+{
+ return PSGetJobName(
+ ConnectionHandle,
+ 0,
+ pOwner,
+ pJobName,
+ pJobRecord,
+ FALSE);
+}
+
+
+/*++
+*******************************************************************
+
+ PSGetJobName
+
+Routine Description:
+
+ Common routine to get the print job configuration from the
+ printcon.dat file.
+
+Arguments:
+
+ ConnectionHandle = The connection handle to use.
+ SearchFlag =
+ pOwner =
+ pJobName = A pointer to return the default job configuration name.
+ pJobRecord = A pointer to return the default job configuration.
+ GetDefault = TRUE = get the default job name, FALSE = Don't get
+ the default job name.
+
+Return Value:
+
+ SUCCESSFUL 0x0000
+ PS_ERR_BAD_VERSION 0x7770
+ PS_ERR_GETTING_DEFAULT 0x7773
+ PS_ERR_OPENING_DB 0x7774
+ PS_ERR_READING_DB 0x7775
+ PS_ERR_READING_RECORD 0x7776
+ PS_ERR_INTERNAL_ERROR 0x7779
+ PS_ERR_NO_DEFAULT_SPECIFIED 0x777B
+ INVALID_CONNECTION 0x8801
+
+*******************************************************************
+--*/
+unsigned int
+PSGetJobName(
+ unsigned int ConnectionHandle,
+ unsigned short SearchFlag,
+ unsigned char *pOwner,
+ unsigned char *pJobName,
+ PPS_JOB_RECORD pJobRecord,
+ unsigned char GetDefault
+ )
+{
+ unsigned char *pSearchJobName;
+ unsigned long ObjectId;
+ FILE *stream = NULL;
+ unsigned int Count;
+ unsigned int Bytes;
+ unsigned int RetCode;
+ unsigned int ConnectionNumber;
+ JOB_NAME_AREA JobNameArea;
+ JOB_RECORD_AREA JobRecord;
+ PRINTCON_HEADER PrintConHeader;
+ unsigned char MailDirPath[NCP_MAX_PATH_LENGTH];
+
+ /** Get the connection number for this connection **/
+
+ RetCode = GetConnectionNumber(ConnectionHandle, &ConnectionNumber);
+ if (RetCode) {
+ goto CommonExit;
+ }
+
+ RetCode = GetBinderyObjectID (ConnectionHandle, LOGIN_NAME,
+ OT_USER, &ObjectId);
+ if (RetCode) {
+ goto CommonExit;
+ }
+
+ /** Build the path to open the file **/
+
+ sprintf(MailDirPath, "SYS:MAIL/%lX/PRINTCON.DAT", SwapLong(ObjectId));
+
+ stream = fopen(NTNWtoUNCFormat( MailDirPath), "rb");
+ if (stream == NULL) {
+ RetCode = PS_ERR_OPENING_DB;
+ goto CommonExit;
+ }
+
+ Bytes = fread( (unsigned char *) &PrintConHeader, sizeof( char), PRINTCON_HEADER_SIZE, stream);
+ if (Bytes < PRINTCON_HEADER_SIZE) {
+ RetCode = PS_ERR_INTERNAL_ERROR;
+ goto CommonExit;
+ }
+
+ /** Check the version number **/
+
+ if ((PrintConHeader.MajorVersion != 3 &&
+ PrintConHeader.MajorVersion != 1) ||
+ PrintConHeader.MinorVersion1 != 1 ||
+ PrintConHeader.MinorVersion2 != 1) {
+
+ RetCode = PS_ERR_BAD_VERSION;
+ goto CommonExit;
+ }
+ /** Get the name we are looking for **/
+
+ if (GetDefault) {
+ if (PrintConHeader.DefaultJobName[0] == 0) {
+ RetCode = PS_ERR_NO_DEFAULT_SPECIFIED;
+ goto CommonExit;
+ }
+ pSearchJobName = PrintConHeader.DefaultJobName;
+ }
+ else {
+ pSearchJobName = pJobName;
+ }
+
+ Count = 0;
+
+ /** Go through all of the job entry to look for the name **/
+
+ while (Count < MAX_JOB_NAME_ENTRY) {
+ Bytes = fread( (unsigned char *) &JobNameArea, sizeof(unsigned char), JOB_NAME_AREA_SIZE, stream);
+ if (Bytes < JOB_NAME_AREA_SIZE) {
+ RetCode = PS_ERR_INTERNAL_ERROR;
+ goto CommonExit;
+ }
+ Count++;
+
+ /** Skip the entry with a null job name **/
+
+ if (JobNameArea.JobName[0] == 0) {
+ continue;
+ }
+
+ /** Is this the job name we are looking for? **/
+
+ if (!_strcmpi(pSearchJobName, JobNameArea.JobName)) {
+ break;
+ }
+ }
+
+ /** See if we found the job name **/
+
+ if (Count > MAX_JOB_NAME_ENTRY) {
+ if (GetDefault) {
+ RetCode = PS_ERR_GETTING_DEFAULT;
+ }
+ else {
+ RetCode = PS_ERR_READING_RECORD;
+ }
+ goto CommonExit;
+ }
+
+ fseek(stream, JobNameArea.JobRecordOffset, SEEK_SET);
+
+ Bytes = fread( (unsigned char *) &JobRecord, sizeof(unsigned char), JOB_RECORD_AREA_SIZE, stream);
+ if (Bytes < JOB_RECORD_AREA_SIZE) {
+ RetCode = PS_ERR_READING_RECORD;
+ goto CommonExit;
+ }
+
+ memset(pJobRecord, 0, PS_JOB_RECORD_SIZE);
+
+ if (JobRecord.NotifyWhenDone) {
+ pJobRecord->PrintJobFlag |= PS_JOB_NOTIFY;
+ }
+ if (JobRecord.BannerFlag) {
+ pJobRecord->PrintJobFlag |= PS_JOB_PRINT_BANNER;
+ }
+ if (JobRecord.DataType) {
+ pJobRecord->PrintJobFlag |= PS_JOB_EXPAND_TABS;
+ }
+ if (JobRecord.FormFeed) {
+ pJobRecord->PrintJobFlag |= PS_JOB_NO_FORMFEED;
+ }
+ if (JobRecord.AutoEndCap) {
+ pJobRecord->PrintJobFlag |= PS_JOB_AUTO_END;
+ }
+ if (JobRecord.TimeoutCount) {
+ pJobRecord->PrintJobFlag |= PS_JOB_TIMEOUT;
+ }
+
+ pJobRecord->Copies = JobRecord.NumberOfCopies;
+ pJobRecord->TabSize = JobRecord.TabSize;
+ pJobRecord->TimeOutCount = JobRecord.TimeoutCount;
+ pJobRecord->LocalPrinter = JobRecord.LocalPrinter;
+
+ strcpy(pJobRecord->Mode, JobRecord.Mode);
+ strcpy(pJobRecord->Device, JobRecord.Device);
+ strcpy(pJobRecord->FormName, JobRecord.FormName);
+ strcpy(pJobRecord->BannerName, JobRecord.BannerName);
+ strcpy(pJobRecord->u.NonDS.PrintQueue, JobRecord.QueueName);
+ strcpy(pJobRecord->u.NonDS.FileServer, JobRecord.ServerName);
+
+ if (GetDefault && pJobName) {
+ strcpy(pJobName, JobNameArea.JobName);
+ }
+
+ if (pOwner) {
+ *pOwner = 0;
+ }
+
+CommonExit:
+
+ if (stream != NULL) {
+ fclose( stream );
+ }
+
+ return RetCode;
+}
diff --git a/private/nw/nwscript/script.c b/private/nw/nwscript/script.c
new file mode 100644
index 000000000..14df55b93
--- /dev/null
+++ b/private/nw/nwscript/script.c
@@ -0,0 +1,3968 @@
+
+/*************************************************************************
+*
+* SCRIPT.C
+*
+* Script routines, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+*************************************************************************/
+
+#include "common.h"
+#include <direct.h>
+#include <time.h>
+#include <ctype.h>
+#include <process.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <time.h>
+
+extern VOID nwShowLastLoginTime( VOID );
+
+#define MAXLEN 256
+#define MAX_NUM_IF 10
+
+#define NUMCOMMAND 44
+
+#define CM_IF 20
+#define CM_ELSE 21
+#define CM_END 22
+
+//
+// 3X and 4X variables
+//
+
+#define IDS_DAY_OF_WEEK 0
+#define IDS_DAY 1
+#define IDS_MONTH_NAME 2
+#define IDS_MONTH 3
+#define IDS_NDAY_OF_WEEK 4
+#define IDS_SHORT_YEAR 5
+#define IDS_YEAR 6
+#define IDS_AM_PM 7
+#define IDS_GREETING_TIME 8
+#define IDS_HOUR24 9
+#define IDS_HOUR 10
+#define IDS_MINUTE 11
+#define IDS_SECOND 12
+#define IDS_FULL_NAME 13
+#define IDS_LOGIN_NAME 14
+#define IDS_USER_ID 15
+#define IDS_PASSWORD_EXPIRES 16
+#define IDS_NETWORK_ADDRESS 17
+#define IDS_FILE_SERVER 18
+#define IDS_ACCESS_SERVER 19
+#define IDS_ERROR_LEVEL 20
+#define IDS_ERRORLEVEL 21
+#define IDS_MACHINE 22
+#define IDS_OS_VERSION 23
+#define IDS_OS 24
+#define IDS_SMACHINE 25
+#define IDS_SHELL_TYPE 26
+#define IDS_STATION 27
+#define IDS_P_STATION 28
+#define IDS_SHELL_VERSION 29
+#define NUMVAR_3X IDS_SHELL_VERSION + 1
+
+#define IDS_LAST_NAME 30
+#define IDS_LOGIN_CONTEXT 31
+#define IDS_NETWARE_REQUESTER 32
+#define IDS_REQUESTER_CONTEXT 33
+#define IDS_ACCOUNT_BALANCE 34
+#define IDS_CN 35
+#define IDS_REQUESTER_VERSION 36
+#define IDS_SURNAME 37
+#define IDS_DOS_REQUESTER 38
+#define IDS_REQUESTER 39
+#define IDS_ADMINISTRATIVE_ASSISTANT 40
+#define IDS_ALLOW_UNLIMITED_CREDIT 41
+#define IDS_DESCRIPTION 42
+#define IDS_EMAIL_ADDRESS 43
+#define IDS_EMPLOYEE_ID 44
+#define IDS_FACSIMILE_TELEPHONE_NUMBER 45
+#define IDS_GROUP_MEMBERSHIP 46
+#define IDS_HIGHER_PRIVILEGES 47
+#define IDS_HOME_DIRECTORY 48
+#define IDS_INITIALS 49
+#define IDS_LANGUAGE 50
+#define IDS_LOCKED_BY_INTRUDER 51
+#define IDS_LOGIN_DISABLED 52
+#define IDS_LOGIN_GRACE_LIMIT 53
+#define IDS_LOGIN_GRACE_REMAINING 54
+#define IDS_LOGIN_INTRUDER_ATTEMPTS 55
+#define IDS_LOGIN_MAXIMUM_SIMULTANEOUS 56
+#define IDS_MAILSTOP 57
+#define IDS_MESSAGE_SERVER 58
+#define IDS_MINIMUM_ACCOUNT_BALANCE 59
+#define IDS_NETWORK 60
+#define IDS_OBJECT_CLASS 61
+#define IDS_OU 62
+#define IDS_PASSWORD_ALLOW_CHANGE 63
+#define IDS_PASSWORD_MINIMUM_LENGTH 64
+#define IDS_PASSWORD_REQUIRED 65
+#define IDS_PASSWORD_UNIQUE_REQUIRED 66
+#define IDS_PASSWORDS_USED 67
+#define IDS_PHYSICAL_DELIVERY_OFFICE_NAME 68
+#define IDS_POSTAL_ADDRESS 69
+#define IDS_POSTAL_CODE 70
+#define IDS_POSTAL_OFFICE_BOX 71
+#define IDS_PRIVATE_KEY 72
+#define IDS_PROFILE 73
+#define IDS_REVISION 74
+#define IDS_SECURITY_EQUALS 75
+#define IDS_SECURITY_FLAGS 76
+#define IDS_SEE_ALSO 77
+#define IDS_SERVER_HOLDS 78
+#define IDS_SUPERVISOR 79
+#define IDS_TELEPHONE_NUMBER 80
+#define IDS_TITLE 81
+#define IDS_CERTIFICATE_VALIDITY_INTERVAL 82
+#define IDS_EQUIVALENT_TO_ME 83
+#define IDS_GENERATIONAL_QUALIFIER 84
+#define IDS_GIVEN_NAME 85
+#define IDS_MAILBOX_ID 86
+#define IDS_MAILBOX_LOCATION 87
+#define IDS_PROFILE_MEMBERSHIP 88
+#define IDS_SA 89
+#define IDS_S 90
+#define IDS_L 91
+#define IDS_ACCESS 92
+#define NUMVAR IDS_ACCESS + 1
+
+/*
+ * String constants.
+ */
+
+/*
+ * Text for default Login Script. Don't change.
+ */
+BYTE DefaultLoginScript[] =
+ "WRITE \"Good %GREETING_TIME, %LOGIN_NAME.\\n\"\n"
+ "MAP DISPLAY OFF\n"
+ "MAP ERRORS OFF\n"
+ "Rem: Set 1st drive to most appropriate directory.\n"
+ "MAP *1:=%FILE_SERVER/SYS:;*1:=%FILE_SERVER/SYS:%LOGIN_NAME\n"
+ "If LOGIN_NAME=\"SUPERVISOR\" || LOGIN_NAME=\"ADMIN\" || LOGIN_NAME=\"SUPERVIS\" THEN MAP *1:=%FILE_SERVER/SYS:SYSTEM\n"
+ "Rem: Set search drives (S2 machine-OS dependent).\n"
+ "MAP INS S1:=%FILE_SERVER/SYS:PUBLIC\n"
+ "MAP INS S2:=%FILE_SERVER/SYS:\n"
+ "Rem: Now display all the current drive settings.\n"
+ "MAP DISPLAY ON\n"
+ "MAP\n"
+ "\0";
+
+char *__SPACES__=" \t";
+
+/*
+ * Do not change the order of this array.
+ */
+char * COMPARE_OPERATORS[] =
+{
+ "!=",
+ "<>",
+ "NOT EQUAL TO",
+ "DOES NOT EQUAL",
+ "NOT EQUAL",
+ "IS NOT EQUAL",
+ "#",
+ "IS NOT", // 7
+ ">=", // 8
+ "IS GREATER THAN OR EQUAL TO",
+ "IS GREATER THAN OR EQUAL",
+ "GREATER THAN OR EQUAL TO",
+ "GREATER THAN OR EQUAL",
+ ">", // 13
+ "IS GREATER THAN",
+ "GREATER THAN",
+ "<=", // 16
+ "IS LESS THAN OR EQUAL TO",
+ "IS LESS THAN OR EQUAL",
+ "LESS THAN OR EQUAL TO",
+ "LESS THAN OR EQUAL",
+ "<", // 21
+ "IS LESS THAN",
+ "LESS THAN",
+ "==", // 24
+ "=",
+ "EQUALS",
+ "EQUAL",
+ "IS",
+ "\0"
+};
+
+int IsNotEqual (int nIndex)
+{
+ return(nIndex < 8);
+}
+
+int IsGreaterOrEqual (int nIndex)
+{
+ return(nIndex >= 8 && nIndex < 13);
+}
+
+int IsGreater (int nIndex)
+{
+ return(nIndex >= 13 && nIndex < 16);
+}
+
+int IsLessOrEqual (int nIndex)
+{
+ return(nIndex >= 16 && nIndex < 21);
+}
+
+int IsLess (int nIndex)
+{
+ return(nIndex >= 21 && nIndex < 24);
+}
+
+/*
+ * Type defs.
+ */
+typedef int (*PFCommandHandler) (char *lpParam);
+
+typedef struct tagCOMMANDTABLE
+{
+ char *commandStr0;
+ char *commandStr1;
+ char *commandStr2;
+ PFCommandHandler commandhandler;
+}COMMANDTABLE;
+
+typedef struct tagLABEL_LIST
+{
+ char *pLabel;
+ char *pNextLine;
+ struct tagLABEL_LIST *pNext;
+}LABEL_LIST, *PLABEL_LIST;
+
+/*
+ * Functions that are in command dispatch table.
+ */
+int AttachHandler (char *lpParam);
+int BreakHandler (char *lpParam);
+int ComspecHandler (char *lpParam);
+int DisplayHandler (char *lpParam);
+int DosBreakHandler (char *lpParam);
+int SetHandler (char *lpParam);
+int LocalSetHandler (char *lpParam);
+int DosVerifyHandler (char *lpParam);
+int DriveHandler (char *lpParam);
+int FireHandler (char *lpParam);
+int ExitHandler (char *lpParam);
+int IfHandler (char *lpParam);
+int ElseHandler (char *lpParam);
+int EndHandler (char *lpParam);
+int IncludeHandler (char *lpParam);
+int MapHandler (char *lpParam);
+int PauseHandler (char *lpParam);
+int WriteHandler (char *lpParam);
+int NullHandler (char *lpParam);
+int GotoHandler (char *lpParam);
+int ShiftHandler (char *lpParam);
+int MachineHandler (char *lpParam);
+int CompatibleHandler(char *lpParam);
+int ClearHandler (char *lpParam);
+int LastLoginTimeHandler(char *lpParam);
+int ContextHandler (char *lpParam);
+int ScriptServerHandler(char *lpParam);
+int NoDefaultHandler (char *lpParam);
+
+/*
+ * Command dispatch table. Do not change.
+ *
+ * If you do, you must change CM_IF, CM_ELSE, and CM_END
+ */
+COMMANDTABLE nwCommand[NUMCOMMAND] =
+{
+ "LOCAL", "DOS", "SET", LocalSetHandler,
+ "TEMP", "DOS", "SET", LocalSetHandler,
+ "TEMPORARY", "DOS", "SET", LocalSetHandler,
+ "LOCAL", "SET", NULL, LocalSetHandler,
+ "TEMP", "SET", NULL, LocalSetHandler,
+ "TEMPORARY", "SET", NULL, LocalSetHandler,
+ "DOS", "SET", NULL, SetHandler,
+ "DOS", "VERIFY", NULL, DosVerifyHandler,
+ "DOS", "BREAK", NULL, DosBreakHandler,
+ "FIRE", "PHASERS", NULL, FireHandler,
+ "ATTACH", NULL, NULL, AttachHandler,
+ "BREAK", NULL, NULL, BreakHandler,
+ "COMSPEC", NULL, NULL, NullHandler,
+ "DISPLAY", NULL, NULL, DisplayHandler,
+ "SET_TIME", NULL, NULL, NullHandler,
+ "SET", NULL, NULL, SetHandler,
+ "DRIVE", NULL, NULL, DriveHandler,
+ "FDISPLAY", NULL, NULL, DisplayHandler,
+ "FIRE", NULL, NULL, FireHandler,
+ "EXIT", NULL, NULL, ExitHandler,
+ "IF", NULL, NULL, IfHandler, // CM_IF
+ "ELSE", NULL, NULL, ElseHandler, // CM_ELSE
+ "END", NULL, NULL, EndHandler, // CM_END
+ "INCLUDE", NULL, NULL, IncludeHandler,
+ "MACHINE", NULL, NULL, MachineHandler,
+ "MAP", NULL, NULL, MapHandler,
+ "PAUSE", NULL, NULL, PauseHandler,
+ "COMPATIBLE", NULL, NULL, CompatibleHandler,
+ "PCCOMPATIBLE", NULL, NULL, CompatibleHandler,
+ "REMARK", NULL, NULL, NullHandler,
+ "REM", NULL, NULL, NullHandler,
+ "SHIFT", NULL, NULL, ShiftHandler,
+ "WAIT", NULL, NULL, PauseHandler,
+ "WRITE", NULL, NULL, WriteHandler,
+ "GOTO", NULL, NULL, GotoHandler,
+ "CLS", NULL, NULL, ClearHandler,
+ "CLEAR", NULL, NULL, ClearHandler,
+ "SWAP", NULL, NULL, NullHandler,
+ "LASTLOGIN", NULL, NULL, LastLoginTimeHandler, // 38
+ "CONTEXT", NULL, NULL, ContextHandler, // 39
+ "SCRIPT_SERVER", NULL, NULL, ScriptServerHandler, // 40
+ "NO_DEFAULT", NULL, NULL, NoDefaultHandler, // 41
+ "CX", NULL, NULL, ContextHandler, // 42
+ "PATH", NULL, NULL, MapHandler, // 43
+};
+
+typedef struct tagVARTABLE
+{
+ char *VarName;
+}VARTABLE;
+
+VARTABLE varTable[NUMVAR] =
+{
+ "DAY_OF_WEEK",
+ "DAY",
+ "MONTH_NAME",
+ "MONTH",
+ "NDAY_OF_WEEK",
+ "SHORT_YEAR",
+ "YEAR",
+ "AM_PM",
+ "GREETING_TIME",
+ "HOUR24",
+ "HOUR",
+ "MINUTE",
+ "SECOND",
+ "FULL_NAME",
+ "LOGIN_NAME",
+ "USER_ID",
+ "PASSWORD_EXPIRES",
+ "NETWORK_ADDRESS",
+ "FILE_SERVER",
+ "ACCESS_SERVER",
+ "ERROR_LEVEL",
+ "ERRORLEVEL",
+ "MACHINE",
+ "OS_VERSION",
+ "OS",
+ "SMACHINE",
+ "SHELL_TYPE",
+ "STATION",
+ "P_STATION",
+ "SHELL_VERSION",
+ "LAST_NAME",
+ "LOGIN_CONTEXT",
+ "NETWARE_REQUESTER",
+ "REQUESTER_CONTEXT",
+ "ACCOUNT_BALANCE",
+ "CN",
+ "REQUESTER_VERSION",
+ "SURNAME",
+ "DOS_REQUESTER",
+ "REQUESTER",
+ "ADMINISTRATIVE_ASSISTANT",
+ "ALLOW_UNLIMITED_CREDIT",
+ "DESCRIPTION",
+ "EMAIL_ADDRESS",
+ "EMPLOYEE_ID",
+ "FACSIMILE_TELEPHONE_NUMBER",
+ "GROUP_MEMBERSHIP",
+ "HIGHER_PRIVILEGES",
+ "HOME_DIRECTORY",
+ "INITIALS",
+ "LANGUAGE",
+ "LOCKED_BY_INTRUDER",
+ "LOGIN_DISABLED",
+ "LOGIN_GRACE_LIMIT",
+ "LOGIN_GRACE_REMAINING",
+ "LOGIN_INTRUDER_ATTEMPTS",
+ "LOGIN_MAXIMUM_SIMULTANEOUS",
+ "MAILSTOP",
+ "MESSAGE_SERVER",
+ "MINIMUM_ACCOUNT_BALANCE",
+ "NETWORK",
+ "OBJECT_CLASS",
+ "OU",
+ "PASSWORD_ALLOW_CHANGE",
+ "PASSWORD_MINIMUM_LENGTH",
+ "PASSWORD_REQUIRED",
+ "PASSWORD_UNIQUE_REQUIRED",
+ "PASSWORDS_USED",
+ "PHYSICAL_DELIVERY_OFFICE_NAME",
+ "POSTAL_ADDRESS",
+ "POSTAL_CODE",
+ "POSTAL_OFFICE_BOX",
+ "PRIVATE_KEY",
+ "PROFILE",
+ "REVISION",
+ "SECURITY_EQUALS",
+ "SECURITY_FLAGS",
+ "SEE_ALSO",
+ "SERVER_HOLDS",
+ "SUPERVISOR",
+ "TELEPHONE_NUMBER",
+ "TITLE",
+ "CERTIFICATE_VALIDITY_INTERVAL",
+ "EQUIVALENT_TO_ME",
+ "GENERATIONAL_QUALIFIER",
+ "GIVEN_NAME",
+ "MAILBOX_ID",
+ "MAILBOX_LOCATION",
+ "PROFILE_MEMBERSHIP",
+ "SA",
+ "S",
+ "L",
+ "ACCESS",
+};
+
+/*
+ * Local functions.
+ */
+void SmartCap(char *ptr);
+int NWGetFileSize (char * lpFileName);
+void LoadFile (char *lpFileName, char *lpFileBuffer, int nFileSize);
+int ProcessLoginScriptFile (char *lpLoginScriptFile);
+void ProcessLoginScript (char *lpLoginScript);
+int ProcessLoginScriptProperty (unsigned char *);
+
+int CreateLabelList (PLABEL_LIST *ppLabelList, char *lpLoginScript);
+void FreeLabelList (LABEL_LIST *pLabelList);
+
+void ExternalCmdHandler(char *lpCommand);
+void BadCommandHandler (char *lpCommand);
+
+void CommandDispatch (char *lpCommand);
+int GetTableIndex(char *lpCommand, char ** prestbuffer);
+
+DWORD SwapLong(DWORD number);
+int EndOfLine (char *buffer);
+char *RemoveSpaces (char * buffer);
+int IsOn (char *lpParam);
+int IsOff (char *lpParam);
+int VarTranslate(char *vartext);
+int QuotedStringTranslate (char *buffer);
+void NotQuotedStringTranslate(char *buffer, BOOL remove_dbs);
+void SetLocalEnv(char *buffer);
+int SetEnv (char *lpEnvLine);
+char *ConvertPercent (char *buffer);
+void GetShellVersion(char *buffer, int index);
+
+/*
+ * Global Defines
+ */
+#define IsWhiteSpace(x) ((x==' ')||(x=='\t')||(x=='\n')||(x=='\r')||(x==0))
+
+/*
+ * Global variables.
+ */
+
+//
+// The following globals are used for goto processing... this allows us
+// to manipulate the line we're processing outside ProcessLoginScript.
+//
+
+LABEL_LIST *pGlobalLabelList;
+char *lpGlobalLine;
+char *lpGlobalLineSeparator;
+int fGlobalHaveNulledLineSeparator;
+int fGlobalExitFlag;
+int fGlobalIfTooDeep;
+
+int fBreakOn = TRUE;
+
+int nCondIndex;
+int aCondVal[MAX_NUM_IF];
+
+int ARGC;
+char **ARGV;
+int nGlobalShiftDelta = 0;
+int fGlobalCompatible = FALSE;
+int fNoDefaultLoginScript = FALSE;
+
+char *LOGIN_NAME;
+char *LAST_NAME;
+char *LOGIN_CONTEXT;
+char *REQUESTER_CONTEXT;
+char *COMMON_NAME;
+char *TYPED_USER_NAME;
+PWCHAR TYPED_USER_NAME_w;
+PBYTE NDSTREE;
+PBYTE PREFERRED_SERVER;
+
+HANDLE hconout = INVALID_HANDLE_VALUE;
+
+unsigned int CONNECTION_ID;
+unsigned int CONNECTION_NUMBER;
+unsigned int SCRIPT_ERROR = 0;
+
+#define REQUESTER_VERSION "V1.20"
+
+extern DWORD GUserObjectID;
+
+int IsEmptyFile (char *lpFile)
+{
+ while (*lpFile != 0)
+ {
+ if (*lpFile != ' ' &&
+ *lpFile != '\t'&&
+ *lpFile != '\n'&&
+ *lpFile != '\r')
+ {
+ return(FALSE);
+ }
+ lpFile++;
+ }
+
+ return(TRUE);
+}
+
+/*
+ * Login was successful. Process both Login Scripts: the System Login
+ * Script and the User Login Script. If there is an EXIT command in the
+ * System Login Script, then we do not process the User Login Script.
+ * If there is no User Login Script, we process a default Login Script,
+ * which is hard-coded internally. See the Login Script appendix in
+ * the NetWare Installation guide for more info.
+ */
+void ProcessLoginScripts (unsigned int conn, char *UserName, int argc, char ** argv, char *lpScript)
+{
+ unsigned int iRet = 0;
+ unsigned long userID ;
+ char pchUserLoginScriptFile[24];
+
+ // Initalize LOGIN_NAME, CONNECTION_ID and CONNECTION_NUMBER.
+ ARGC = argc;
+ ARGV = argv;
+ LOGIN_NAME = UserName;
+ CONNECTION_ID = conn;
+
+ // Initialize some 4X variables
+ if ( fNDS )
+ {
+ COMMON_NAME = UserName;
+
+ LOGIN_CONTEXT = malloc ( CONTEXT_MAX );
+ strcpy( LOGIN_CONTEXT, REQUESTER_CONTEXT );
+
+ LAST_NAME = malloc( MAXLEN );
+ NDSGetVar ( "SURNAME", LAST_NAME, MAXLEN );
+ }
+ else {
+ LAST_NAME = UserName;
+ COMMON_NAME = UserName;
+ LOGIN_CONTEXT = "";
+ REQUESTER_CONTEXT = "";
+ }
+
+ if (iRet = GetConnectionNumber (conn, &CONNECTION_NUMBER))
+ {
+ DisplayError (iRet, "GetConnectionNumber");
+ return;
+ }
+
+ if (lpScript)
+ {
+ if (!ProcessLoginScriptFile(lpScript))
+ DisplayMessage(IDR_NO_SCRIPT_FILE, lpScript);
+ }
+ else
+ {
+ if ( fNDS )
+ {
+ unsigned char Object[128];
+ unsigned char ProfileObject[256];
+ PBYTE p;
+ int err;
+
+ // Browse back from user's node to first occurrence
+ // or organizational unit or organization and look for
+ // system script there. If the nearest OU or O doesn't have
+ // a system script, don't run one.
+
+ for ( p = TYPED_USER_NAME; p ; p = strchr ( p, '.' ) )
+ {
+
+ p++;
+
+ if ( *p == 'O' && *(p+1) == 'U' && *(p+2) == '=' )
+ break;
+
+ if ( *p == 'O' && *(p+1) == '=' )
+ break;
+ }
+
+ if ( p != NULL )
+ {
+ ProcessLoginScriptProperty( p );
+ }
+
+ // profile login script.
+
+ if ( !NDSGetUserProperty ( "Profile", ProfileObject, 256, NULL, NULL) )
+ {
+ ConvertUnicodeToAscii( ProfileObject );
+ ProcessLoginScriptProperty( ProfileObject );
+ }
+
+ // user login script
+
+ if ( (!ProcessLoginScriptProperty( TYPED_USER_NAME )) &&
+ (!fNoDefaultLoginScript) )
+ {
+ ProcessLoginScript (DefaultLoginScript);
+ }
+ }
+ else
+ {
+ static char SysLoginScriptFile[] = "SYS:PUBLIC/NET$LOG.DAT" ;
+
+ // Process system login script file.
+ ProcessLoginScriptFile (SysLoginScriptFile);
+
+ // Check if user login script exists.
+ if (iRet = GetBinderyObjectID (conn, UserName, OT_USER,
+ &userID))
+ return;
+
+ sprintf(pchUserLoginScriptFile, "SYS:MAIL/%lx/LOGIN", SwapLong(userID));
+
+ if ( (!ProcessLoginScriptFile (pchUserLoginScriptFile)) &&
+ (!fNoDefaultLoginScript) )
+ {
+ ProcessLoginScript (DefaultLoginScript);
+ }
+ }
+ }
+}
+
+int ProcessLoginScriptFile (char *lpLoginScriptFile)
+{
+ int nFileSize = 0, bEmpty;
+ char *lpLoginScript;
+
+ nFileSize = NWGetFileSize (lpLoginScriptFile);
+
+ if (nFileSize <= 2)
+ return(FALSE);
+
+ // system login script exists.
+ lpLoginScript = malloc (nFileSize);
+ if (lpLoginScript == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ LoadFile (lpLoginScriptFile, lpLoginScript, nFileSize);
+
+ bEmpty = IsEmptyFile(lpLoginScript);
+
+ if (!bEmpty)
+ ProcessLoginScript (lpLoginScript);
+
+ free (lpLoginScript);
+
+ return(!bEmpty);
+}
+
+
+/*
+ * Retrieve and process the Login Script property
+ */
+int ProcessLoginScriptProperty ( unsigned char * Object )
+{
+ unsigned int nFileSize = 0;
+ unsigned int Actual = 0;
+ unsigned int bEmpty;
+ char *lpLoginScript;
+ HANDLE Stream;
+ int err;
+ unsigned int i,j;
+
+ if ( NDSfopenStream ( Object, "Login Script", &Stream, &nFileSize ) )
+ return(FALSE);
+
+ if ( nFileSize <= 2)
+ return(FALSE);
+
+ // login script exists.
+ lpLoginScript = malloc (nFileSize+2);
+ if (lpLoginScript == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ memset(lpLoginScript, 0, nFileSize+2);
+
+ if ( !ReadFile ( Stream, lpLoginScript, nFileSize, &Actual, NULL ) )
+ {
+ bEmpty = TRUE;
+ }
+#ifdef BUGBUG // ReadFile is returning wrong lengths
+ else if ( Actual != nFileSize )
+ {
+ bEmpty = TRUE;
+ }
+#endif
+ else if ( IsEmptyFile(lpLoginScript) )
+ bEmpty = TRUE;
+ else
+ bEmpty = FALSE;
+
+ for ( i = 0, j = 0; i < nFileSize; i++, j++ )
+ {
+ if (( lpLoginScript[i] == '\r' ) &&
+ ( lpLoginScript[i+1] == '\n' ) )
+ i++;
+
+ lpLoginScript[j] = lpLoginScript[i];
+ }
+
+ while ( j < nFileSize )
+ {
+ lpLoginScript[j++] = 0;
+ }
+
+ CloseHandle( Stream );
+
+ if (!bEmpty)
+ ProcessLoginScript (lpLoginScript);
+
+ free (lpLoginScript);
+
+ return(!bEmpty);
+}
+
+/*
+ * Return the size of the file.
+ */
+int NWGetFileSize (char * lpFileName)
+{
+ int nFileSize = 0;
+ FILE * stream;
+
+ do
+ {
+ if ((stream = fopen (NTNWtoUNCFormat(lpFileName), "r")) == NULL)
+ break;
+
+ while (feof (stream) == 0)
+ {
+ fgetc (stream);
+ nFileSize++;
+ }
+
+ if (fclose (stream))
+ nFileSize = 0;
+ }while (FALSE);
+
+
+ return(nFileSize);
+}
+
+/*
+ * Read the file into memory pointed by lpFileBuffer.
+ */
+void LoadFile (char *lpFileName, char *lpFileBuffer, int nFileSize)
+{
+ FILE * stream;
+
+ if ((stream = fopen (NTNWtoUNCFormat(lpFileName), "r")) != NULL)
+ {
+ fread (lpFileBuffer, sizeof (char), nFileSize, stream);
+ fclose (stream);
+ }
+
+ *(lpFileBuffer+nFileSize-1) = 0;
+
+}
+
+/*
+ * Process Login Script that is in memory pointed by lpLoginScript
+ * line by line.
+ */
+void ProcessLoginScript (char *lpLoginScript)
+{
+ nCondIndex = -1;
+ fGlobalExitFlag = FALSE;
+ fGlobalIfTooDeep = FALSE;
+
+ lpGlobalLine = lpLoginScript; // we start at the top of the login script
+
+ if (!CreateLabelList (&pGlobalLabelList, lpLoginScript))
+ {
+ if (pGlobalLabelList != NULL) {
+
+ FreeLabelList (pGlobalLabelList);
+ pGlobalLabelList = NULL;
+ }
+ return;
+ }
+
+ while (*lpGlobalLine != 0) {
+
+ //
+ // search for the end of the current line and replace with a null
+ //
+
+ if (lpGlobalLineSeparator = strchr(lpGlobalLine, '\n')) {
+
+ //
+ // we may reset this manually in the goto handler, remember so that
+ // we don't trample anything needlessly.
+ //
+
+ *lpGlobalLineSeparator = 0;
+ fGlobalHaveNulledLineSeparator = TRUE;
+
+ } else {
+
+ fGlobalHaveNulledLineSeparator = FALSE;
+ }
+
+ //
+ // Now lpGlobalLine points to one line only.
+ //
+
+ CommandDispatch (lpGlobalLine);
+
+ if (fGlobalExitFlag)
+ {
+ if (fGlobalIfTooDeep)
+ DisplayMessage(IDR_ORIGINAL_LINE_WAS, lpGlobalLine);
+ break;
+ }
+
+ if (lpGlobalLineSeparator) {
+
+ if ( fGlobalHaveNulledLineSeparator ) {
+
+ *lpGlobalLineSeparator = '\n'; // recover the changes made.
+ fGlobalHaveNulledLineSeparator = FALSE;
+ }
+
+ lpGlobalLine = lpGlobalLineSeparator + 1; // next line please
+
+ } else {
+
+ break;
+ }
+ }
+
+ if (pGlobalLabelList != NULL) {
+ FreeLabelList (pGlobalLabelList);
+ pGlobalLabelList = NULL;
+ }
+}
+
+/*
+ * Scan the login script, put labels in a link list and comment out
+ * those label lines.
+ */
+int CreateLabelList (PLABEL_LIST *ppLabelList, char *lpLoginScript)
+{
+ char *lpLine = lpLoginScript, *lpEnd, *lpLabel, *lpTemp;
+ int nLen;
+ PLABEL_LIST *ppNext = ppLabelList;
+
+ while (*lpLine != 0)
+ {
+ if (lpEnd = strchr (lpLine, '\n'))
+ *lpEnd = 0;
+
+ // Now lpLine points to one line only.
+ lpLabel = RemoveSpaces (lpLine);
+ if (isalnum (*lpLabel) || (*lpLabel == '%'))
+ {
+ lpTemp = lpLabel;
+ nLen = 0;
+ while (*lpTemp != 0 && *lpTemp != ' ' && *lpTemp != '\t' && *lpTemp != ':')
+ {
+ if (IsDBCSLeadByte(*lpTemp))
+ {
+ lpTemp++;
+ nLen++;
+ }
+
+ lpTemp++;
+ nLen++;
+ }
+
+ lpTemp = RemoveSpaces (lpTemp);
+ if (*lpTemp == ':' && EndOfLine (lpTemp+1))
+ {
+ // The Line is label line.
+ if ((*ppNext = malloc (sizeof (LABEL_LIST))) == NULL ||
+ ((*ppNext)->pLabel = malloc (nLen+1)) == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return(FALSE);
+ }
+
+ SmartCap(lpLabel);
+ strncpy ((*ppNext)->pLabel, lpLabel, nLen);
+ *((*ppNext)->pLabel+nLen) = 0;
+ (*ppNext)->pNextLine = lpEnd? lpEnd+1 : lpEnd;
+ (*ppNext)->pNext = NULL;
+ ppNext = &((*ppNext)->pNext);
+
+ // Comment out the label line.
+ *(lpLine) = ';';
+ }
+ }
+
+ if (lpEnd)
+ {
+ *lpEnd = '\n'; // recover the changes made.
+ lpLine = lpEnd+1;
+ }
+ else
+ break;
+ }
+
+ return(TRUE);
+}
+
+/*
+ * Free up the memory allocated for the link list.
+ */
+void FreeLabelList (LABEL_LIST *pLabelList)
+{
+ LABEL_LIST *pNext = pLabelList;
+
+ while (pLabelList)
+ {
+ pNext = pLabelList->pNext;
+ free (pLabelList->pLabel);
+ free (pLabelList);
+ pLabelList = pNext;
+ }
+}
+
+/*
+ * Dispatch to command hander according to the command.
+ */
+void CommandDispatch (char *lpCommand)
+{
+ char buffer[MAXLEN];
+ char *restBuffer;
+ int index, fCommandHandled = FALSE;
+ int nTemp = -1;
+
+ // Get rid of leading spaces.
+ lpCommand = RemoveSpaces(lpCommand);
+
+ // Don't do anything if it's a comment line or empty line.
+ if (*lpCommand == ';' || *lpCommand == '*' || *lpCommand == '\0' ||
+ *lpCommand == '\r'|| *lpCommand == '\n')
+ return;
+
+ do // FALSE loop.
+ {
+ // Make sure the command line is not too long to process.
+ if (strlen (lpCommand) > MAXLEN -1) {
+ break;
+ }
+
+ // Make a copy of the command line to buffer.
+ strcpy (buffer, lpCommand);
+
+ // external command line.
+ if (*buffer == '#')
+ {
+ ExternalCmdHandler (buffer);
+ return;
+ }
+
+ // Get the command index in the command table.
+ if ((index = GetTableIndex(buffer, &restBuffer)) == -1)
+ break;
+
+ // Dispatch to the corresponding command handler.
+ if (nCondIndex > -1 &&
+ !aCondVal[nCondIndex] &&
+ index != CM_IF &&
+ index != CM_ELSE &&
+ index != CM_END)
+ fCommandHandled = TRUE;
+ else
+ fCommandHandled = (*nwCommand[index].commandhandler)(restBuffer);
+
+ } while (FALSE);
+
+ if (!fCommandHandled) {
+ BadCommandHandler (lpCommand);
+ }
+}
+
+/*
+ * Used by GetTableIndex().
+ * This function should capitalize the entire command string except
+ * those in quotes.
+ */
+void SmartCap(char *ptr)
+{
+ int inquotes = (*ptr == '\"');
+ char *pNext;
+
+ while (*ptr)
+ {
+ if (!inquotes)
+ {
+ if (IsDBCSLeadByte(*ptr))
+ *((int *)ptr) = toupper ((int)*ptr);
+ else
+ *ptr = (char) toupper((int)*ptr);
+ }
+
+ pNext = NWAnsiNext(ptr);
+
+ if (*pNext == '\"' && *ptr != '\\')
+ inquotes = !inquotes;
+
+ ptr = pNext;
+ }
+}
+
+/*
+ * Return the index of the command in the command dispatch table.
+ * Return -1 if the command is not found in the command dispatch table.
+ */
+int GetTableIndex(char *buffer, char **prestBuffer)
+{
+ int i, nStrLen;
+
+ // Upcase every thing except those in quotes.
+ SmartCap (buffer);
+
+ for (i=0; i<NUMCOMMAND; i++)
+ {
+ if (*(WORD *)nwCommand[i].commandStr0 != *(WORD *)buffer)
+ continue;
+
+ nStrLen = strlen (nwCommand[i].commandStr0);
+
+ if (strncmp(nwCommand[i].commandStr0, buffer, nStrLen))
+ continue;
+
+ *prestBuffer = buffer + nStrLen;
+ *prestBuffer = RemoveSpaces (*prestBuffer);
+
+ if (nwCommand[i].commandStr1)
+ {
+ nStrLen = strlen (nwCommand[i].commandStr1);
+
+ if (strncmp(nwCommand[i].commandStr1, *prestBuffer, nStrLen))
+ continue;
+
+ *prestBuffer += nStrLen;
+ *prestBuffer = RemoveSpaces (*prestBuffer);
+
+ if (nwCommand[i].commandStr2)
+ {
+ nStrLen = strlen (nwCommand[i].commandStr2);
+
+ if (strncmp(nwCommand[i].commandStr2, *prestBuffer, nStrLen))
+ continue;
+
+ *prestBuffer += nStrLen;
+ *prestBuffer = RemoveSpaces (*prestBuffer);
+ }
+ }
+
+ return (i);
+ }
+
+ return(-1);
+}
+
+/*
+ * Goto label... We modify the globals controlling what line we're on.
+ */
+int GotoHandler (char *lpParam)
+{
+ int fLabelFound = FALSE;
+ char *lpLabel, *lpEnd, chEnd;
+ LABEL_LIST *pLabelList = pGlobalLabelList;
+
+ lpLabel = lpParam;
+ lpLabel = RemoveSpaces (lpLabel);
+
+ //
+ // find the end of the label, we'll slam in a null for the search and
+ // restore the char after we're done searching.
+ //
+
+ lpEnd = lpLabel;
+ while (*lpEnd != 0 &&
+ *lpEnd != ' ' &&
+ *lpEnd != '\t' &&
+ *lpEnd != '\r' &&
+ *lpEnd != '\n')
+ {
+ if (*lpEnd == ':')
+ return(FALSE);
+ else
+ lpEnd = NWAnsiNext(lpEnd);
+ }
+
+ chEnd = *lpEnd;
+ *lpEnd = 0;
+
+ while (pLabelList)
+ {
+ if (!_stricmp (pLabelList->pLabel, lpLabel))
+ {
+ if ( fGlobalHaveNulledLineSeparator )
+ {
+
+ *lpGlobalLineSeparator = '\n'; // recover the changes made.
+ fGlobalHaveNulledLineSeparator = FALSE;
+ }
+
+ lpGlobalLine = pLabelList->pNextLine;
+
+ lpGlobalLineSeparator = lpGlobalLine ? (lpGlobalLine - 1) : NULL;
+
+ fLabelFound = TRUE;
+ break;
+ }
+
+ pLabelList = pLabelList->pNext;
+ }
+
+ if (!fLabelFound)
+ {
+ DisplayMessage (IDR_LABEL_NOT_FOUND, lpLabel);
+ fGlobalExitFlag = TRUE;
+ }
+
+ *lpEnd = chEnd;
+ return( TRUE );
+}
+
+/*
+ * Attach [FileServer[/UserName[;Password]]]
+ */
+int AttachHandler (char *lpParam)
+{
+ unsigned int iRet = 0;
+ int fCommandHandled = FALSE;
+ char serverName[MAX_NAME_LEN] = "";
+ char userName[MAX_NAME_LEN] = "";
+ char password[MAX_PASSWORD_LEN] = "";
+ char *lpSlash, *lpSemiColon, *lpServerName, *lpUserName;
+ unsigned int conn;
+ int bAlreadyAttached = FALSE, bReadPassword = TRUE;
+
+ do // FALSE loop.
+ {
+ NotQuotedStringTranslate (lpParam, TRUE);
+
+ // Make sure that there is at most 1 slash.
+ lpSlash = strchr (lpParam, '\\');
+
+ if (lpSlash == NULL)
+ {
+ lpSlash = strchr (lpParam, '/');
+ if (lpSlash != NULL && strchr (lpSlash+1, '/'))
+ break;
+ }
+ else
+ {
+ if (strchr (lpParam, '/') ||
+ strchr (lpSlash+1, '/') ||
+ strchr (lpSlash+1, '\\'))
+ break;
+ }
+
+ // Break the string at slash.
+ if (lpSlash)
+ *lpSlash = 0;
+
+ // Server name should not contain semicolon.
+ if (strchr (lpParam, ';'))
+ break;
+
+ lpServerName = strtok (lpParam, __SPACES__);
+
+ if (lpServerName = NULL)
+ {
+ if (lpSlash)
+ break;
+ }
+ else
+ {
+ // Make sure that there is only one name in front of the slash.
+ if (strtok (NULL, __SPACES__))
+ break;
+
+ // Copy the server name to the buffer.
+ if (strlen (lpParam) > MAX_NAME_LEN-1)
+ break;
+
+ strcpy (serverName, lpParam);
+
+ if (lpSlash)
+ {
+ lpSemiColon = strchr (lpSlash+1, ';');
+ if (lpSemiColon)
+ *lpSemiColon = 0;
+
+ lpUserName = strtok (lpSlash+1, __SPACES__);
+ if (lpUserName)
+ {
+ if ( strtok (NULL, __SPACES__))
+ break;
+
+ if (strlen (lpUserName) > MAX_NAME_LEN-1 )
+ break;
+
+ strcpy (userName, lpUserName);
+ }
+
+ if (lpSemiColon)
+ {
+ if (strlen (lpSemiColon+1) > MAX_PASSWORD_LEN-1)
+ break;
+ strcpy (password, strtok (lpSemiColon+1, __SPACES__));
+ xstrupr (password);
+ bReadPassword = FALSE;
+ }
+ }
+ }
+
+ fCommandHandled = TRUE;
+
+ if (serverName[0] == 0)
+ {
+ DisplayMessage(IDR_ENTER_SERVER_NAME);
+ if (!ReadName(serverName))
+ break;
+
+ DisplayMessage(IDR_ENTER_LOGIN_NAME, serverName);
+ if (!ReadName(userName))
+ break;
+ }
+ else if (userName[0] == 0)
+ strcpy (userName, LOGIN_NAME);
+
+ if (iRet = CAttachToFileServer(serverName, &conn, &bAlreadyAttached))
+ {
+ if (!SCRIPT_ERROR)
+ SCRIPT_ERROR = iRet;
+ break;
+ }
+
+ // Do not need this connection
+ DetachFromFileServer (conn);
+
+#ifdef BUGBUG // not reliable
+ if (bAlreadyAttached)
+ {
+ DisplayMessage(IDR_ATTACHED, serverName);
+ break;
+ }
+#endif
+
+ if (Login(userName, serverName, password, bReadPassword))
+ {
+ // Clear out the password
+ memset( password, 0, sizeof( password ) );
+
+ // Ask for user name
+
+ DisplayMessage(IDR_ENTER_LOGIN_NAME, serverName);
+ if (!ReadName(userName))
+ break;
+
+ if (Login(userName, serverName, password, bReadPassword))
+ {
+ // Clear out the password
+ memset( password, 0, sizeof( password ) );
+ break;
+ }
+ }
+
+ // Clear out the password
+
+ memset( password, 0, sizeof( password ) );
+
+ AddServerToAttachList( serverName, LIST_3X_SERVER );
+
+ } while (FALSE);
+
+ return(fCommandHandled);
+}
+
+/*
+ * BREAK ON, enable ctrl-c, ctrl-break
+ * BREAK OFF, disable ctrl-c, ctrl-break
+ */
+int BreakHandler (char *lpParam)
+{
+ int fCommandHandled = TRUE;
+
+ if (IsOn(lpParam))
+ {
+ if (!fBreakOn)
+ BreakOn();
+ }
+ else if (IsOff(lpParam))
+ {
+ if (fBreakOn)
+ BreakOff();
+ }
+ else
+ fCommandHandled = FALSE;
+
+ return(fCommandHandled);
+}
+
+
+/*
+ * DISPLAY [pathname]file
+ * FDISPLAY [pathname]file
+ */
+int DisplayHandler (char *lpParam)
+{
+ FILE * stream;
+
+ NotQuotedStringTranslate (lpParam, TRUE);
+
+ if ((stream = fopen (lpParam, "r")) != NULL)
+ {
+ while (feof (stream) == 0)
+ _fputchar(fgetc (stream));
+
+ fclose (stream);
+ DisplayMessage(IDR_NEWLINE);
+ }
+
+ return(TRUE);
+}
+
+/*
+ * DOS BREAK ON, enable ctrl-break checking for DOS
+ * DOS BREAK OFF, disable ctrl-break checking for DOS
+ */
+int DosBreakHandler (char *lpParam)
+{
+ int fCommandHandled = TRUE;
+
+ if (IsOn (lpParam))
+ system ("BREAK ON");
+ else if(IsOff (lpParam))
+ system ("BREAK OFF");
+ else
+ fCommandHandled = FALSE;
+
+ return(fCommandHandled);
+}
+
+/*
+ * Used by SetHandler() and LocalSetHandler()
+ * Return TRUE if lpParam points to name = "value", and set
+ * lpParam to "name=value" on return.
+ * Return FALSE otherwise.
+ */
+int VerifySetFormat (char *lpParam)
+{
+ int fCorrect = FALSE;
+ char buffer[MAXLEN];
+ char *lpBuffer = buffer;
+
+ strcpy (buffer, lpParam);
+
+ do
+ {
+ while (*lpBuffer != 0 && *lpBuffer != '=' && *lpBuffer != ' ' && *lpBuffer != '\t')
+ lpBuffer = NWAnsiNext(lpBuffer);
+
+ lpParam[lpBuffer-buffer]=0;
+ strcat (lpParam, "=");
+
+ if (*lpBuffer != '=')
+ lpBuffer = RemoveSpaces (lpBuffer);
+
+ if (*lpBuffer != '=')
+ break;
+
+ lpBuffer = RemoveSpaces (lpBuffer+1);
+
+ if (*lpBuffer)
+ {
+ if (!QuotedStringTranslate (lpBuffer))
+ break;
+
+ strcat (lpParam, lpBuffer);
+ }
+
+ fCorrect = TRUE;
+ }while (FALSE);
+
+ return(fCorrect);
+}
+
+/*
+ * Used by SetHandler() and LocalSetHandler()
+ * Set the local environment variable.
+ * Don't free the memory allocated because the environment variable will
+ * point to free space otherwise.
+ */
+void SetLocalEnv(char *buffer)
+{
+ char *lpEnvString;
+ lpEnvString = malloc(strlen (buffer) + 1);
+
+ if (lpEnvString == NULL)
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ else
+ {
+ strcpy (lpEnvString, buffer);
+ _putenv (lpEnvString);
+ }
+}
+
+/*
+ * Set Dos environment variable.
+ * [DOS] SET name = "value"
+ */
+int SetHandler (char *lpParam)
+{
+
+ int fCommandHandled;
+
+ fCommandHandled = VerifySetFormat(lpParam);
+
+ if (fCommandHandled)
+ {
+
+ if ( _strnicmp( "COMSPEC=", lpParam, strlen( "COMSPEC=" ) ) )
+ {
+ SetLocalEnv(lpParam);
+ SetEnv (lpParam);
+ }
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * Set local Dos environment variable.
+ * [OPTION] [DOS] SET name = "value"
+ */
+int LocalSetHandler (char *lpParam)
+{
+ int fCommandHandled;
+
+ fCommandHandled = VerifySetFormat(lpParam);
+
+ if (fCommandHandled)
+ if ( _strnicmp( "COMSPEC=", lpParam, strlen( "COMSPEC=" ) ) )
+ {
+ SetLocalEnv (lpParam);
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * Used by DosVerifyHandler().
+ * Turn /V option of copy on.
+ */
+void DosVerifyOn(void)
+{
+}
+
+/*
+ * Used by DosVerifyHandler().
+ * Turn /V option of copy off.
+ */
+void DosVerifyOff(void)
+{
+}
+
+/*
+ * DOS VERYFY [ON|OFF], Turn /V option of copy on or off.
+ */
+int DosVerifyHandler (char *lpParam)
+{
+ int fCommandHandled = TRUE;
+
+ if (IsOn(lpParam))
+ DosVerifyOn();
+ else if (IsOff(lpParam))
+ DosVerifyOff();
+ else
+ fCommandHandled = FALSE;
+
+ return(fCommandHandled);
+}
+
+/*
+ * DRIVE [driveletter: | n*:], set the default drive to the one specified.
+ */
+int DriveHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE;
+ WORD driveNum=0, n;
+ char *pColon;
+
+ do // FALSE loop.
+ {
+ if ((pColon = strchr (lpParam, ':')) == NULL ||
+ !EndOfLine (pColon + 1))
+ break;
+
+ if (*lpParam == '*')
+ {
+ *pColon = 0;
+ if ((n = atoi (lpParam+1)) < 1)
+ break;
+
+ GetFirstDrive (&driveNum);
+ driveNum += (n-1);
+ }
+ else if (pColon == lpParam+1 && isupper(*lpParam))
+ driveNum = *lpParam - 'A' + 1;
+ else
+ break;
+
+ if (_chdrive (driveNum))
+ DisplayMessage(IDR_ERROR_SET_DEFAULT_DRIVE, 'A'+driveNum-1);
+ else
+ ExportCurrentDrive( driveNum );
+
+ fCommandHandled = TRUE;
+
+ } while (FALSE);
+
+ return(fCommandHandled);
+}
+
+/*
+ * Used by FireHandler()
+ * Return TRUE if lpTemp points to the legal end of fire statement, ie
+ * [TIMES][COMMENTS]. It also set the *lpTemp to 0 if lpTemp is not NULL.
+ * Return FALSE otherwise.
+ */
+int IsEndOfFireCmd (char *lpTemp)
+{
+ int fEnd = FALSE;
+ do
+ {
+ if (*lpTemp != 0)
+ {
+ if (*lpTemp != ' ' && *lpTemp != '\t' && *lpTemp != '\r')
+ break;
+
+ *lpTemp = 0;
+
+ lpTemp = RemoveSpaces (lpTemp+1);
+
+ if (!strncmp (lpTemp, "TIMES", 5))
+ lpTemp += 5;
+
+ if (!EndOfLine (lpTemp))
+ break;
+ }
+
+ fEnd = TRUE;
+ }while (FALSE);
+
+ return(fEnd);
+}
+
+/*
+ * [FIRE | FIRE PHASERS] n TIMES.
+ */
+int FireHandler (char *lpParam)
+{
+ char *lpTemp, vartext[MAXLEN];
+ int n = 0, nLen;
+ time_t ltimeStart, ltimeEnd;
+
+ if (EndOfLine (lpParam))
+ n = 1;
+ else if (isdigit(*lpParam))
+ {
+ lpTemp = lpParam;
+ while (isdigit(*lpTemp))
+ lpTemp++;
+
+ if (IsEndOfFireCmd (lpTemp))
+ n = atoi (lpParam);
+ }
+ else if (*lpParam == '%')
+ {
+ strcpy (vartext, lpParam+1);
+ if (((nLen = VarTranslate (lpParam)) != 0) &&
+ EndOfLine (lpParam+1+nLen))
+ n = atoi (vartext);
+ }
+
+ if (n < 0)
+ return(FALSE);
+ else if (n == 0) // Compatible with NetWare.
+ n = 1;
+
+ while (n--)
+ {
+ _beep( 610, 100 );
+ _beep( 440, 50 );
+ time(&ltimeStart);
+ do
+ {
+ time(&ltimeEnd);
+ }while (ltimeEnd-ltimeStart == 0);
+ }
+
+ return(TRUE);
+}
+
+/*
+ * EXIT, terminate login script processing.
+ */
+int ExitHandler (char *lpParam)
+{
+ int n;
+ char buffer[16], *argv[10];
+
+ if (EndOfLine (lpParam))
+ CleanupExit(0);
+ else if (QuotedStringTranslate (lpParam))
+ {
+ if (!fGlobalCompatible)
+ {
+ GetShellVersion (buffer, IDS_MACHINE);
+ if (_stricmp (buffer, "IBM_PC"))
+ {
+ DisplayMessage(IDR_EXIT_NOT_SUPPORTED);
+ return(TRUE);
+ }
+ }
+
+ argv[0] = strtok (lpParam, __SPACES__);
+
+ for (n = 1; n < 9; n++)
+ {
+ if ((argv[n] = strtok (NULL, __SPACES__)) == NULL)
+ break;
+ }
+
+ argv[9] = NULL;
+
+ if ((SCRIPT_ERROR = _spawnvp (P_WAIT, argv[0], argv)) == -1)
+ DisplayMessage(IDR_BAD_COMMAND);
+
+ CleanupExit (0);
+ }
+ else
+ return(FALSE);
+}
+
+BOOL nwVarNameCompare(LPCSTR src,LPCSTR target)
+{
+ CHAR szTempName[64];
+ LPSTR pT = szTempName;
+
+ if (!_strnicmp(src,target,strlen(target))) {
+ //
+ // try to reject obvious problems like
+ // %LJUNK where %L would be fine
+ //
+ if ( !isalpha(src[strlen(target)]) )
+ return 0;
+ else
+ return 1;
+ }
+
+ strcpy(szTempName,target);
+
+ while (*pT) {
+ if (!IsDBCSLeadByte(*pT)) {
+ if ('_' == *pT)
+ *pT = ' ';
+ }
+ pT = NWAnsiNext(pT);
+ }
+
+ if (!_strnicmp(src,szTempName,strlen(szTempName))) {
+ //
+ // try to reject obvious problems like
+ // %LJUNK where %L would be fine
+ //
+ if ( !isalpha(src[strlen(target)]) )
+ return 0;
+ else
+ return 1;
+ }
+
+ return 1;
+}
+
+
+/*
+ * Used by the EvalSingleCond() in IfHandler()
+ * Return TRUE if buffer is the right member of condition statement.
+ * *pfCondition is TRUE if the condition meet, FALSE if not.
+ * *ppRest points to the end of the condition statement.
+ * Return FALSE if buffer is not the right member of condition statement.
+ */
+int MemberOf (char *buffer, int *pfCondition, char **ppRest)
+{
+ int i, nChar, fSucceed = FALSE;
+ char *lpTemp;
+ BYTE dataBuffer[128];
+ unsigned char moreFlag;
+ unsigned char propertyType;
+ unsigned long dwObjectId, *pdwGroups;
+ char GroupName[MAXLEN];
+ unsigned char segment;
+
+ *pfCondition = FALSE;
+ do
+ {
+ if ((buffer = strchr (buffer, '\"')) == NULL)
+ break;
+
+ if ((lpTemp = strchr (buffer+1, '\"')) == NULL)
+ break;
+
+ nChar = lpTemp - buffer + 1;
+
+ if (nChar >= MAXLEN)
+ break;
+
+ strncpy (GroupName, buffer, nChar);
+ GroupName[nChar] = 0;
+ if (!QuotedStringTranslate (GroupName))
+ break;
+
+ fSucceed = TRUE;
+ *pfCondition = FALSE;
+ *ppRest = RemoveSpaces (lpTemp+1);
+
+ if (strlen(GroupName) > MAX_NAME_LEN)
+ break;
+
+ if ( fNDS )
+ {
+ if ( IsMemberOfNDSGroup( GroupName ) )
+ {
+ *pfCondition = TRUE;
+ return(TRUE);
+ }
+
+ }
+ else
+ {
+ if (GetBinderyObjectID (CONNECTION_ID,
+ _strupr(GroupName),
+ OT_USER_GROUP,
+ &dwObjectId) )
+ goto done;
+
+ //
+ // For all the group ID's, try and find a match
+ //
+ for ( segment = 1, moreFlag = TRUE; moreFlag && segment; segment++ )
+ {
+ if ( NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "GROUPS_I'M_IN",
+ segment,
+ dataBuffer,
+ &moreFlag,
+ &propertyType))
+ goto done;
+
+ pdwGroups = (unsigned long *) dataBuffer;
+
+ for (i = 0; i < 32 && *(pdwGroups+i); i++)
+ {
+ if (*(pdwGroups+i) == dwObjectId)
+ {
+ *pfCondition = TRUE;
+ return(TRUE);
+ }
+ }
+ }
+ }
+
+ *pfCondition = FALSE;
+ fSucceed = TRUE;
+ } while (FALSE);
+
+done:
+
+ return(fSucceed);
+}
+
+/*
+ * Used by IsCompare() in EvalSingleCond() in IfHandler()
+ * Return the next token.
+ */
+char *GetNextPart (char *lpTemp)
+{
+ INT i;
+
+ if (strncmp (lpTemp, "VALUE", 5) == 0)
+ lpTemp = RemoveSpaces (lpTemp+5);
+
+ if (*lpTemp == '\"')
+ {
+ lpTemp++;
+ while (*lpTemp != 0 && *lpTemp != '\"')
+ lpTemp = NWAnsiNext(lpTemp);
+
+ if (*lpTemp == 0)
+ return(NULL);
+ else
+ lpTemp++;
+ }
+ else if (*lpTemp == '<')
+ {
+ while (*lpTemp != 0 && *lpTemp != '>')
+ lpTemp = NWAnsiNext(lpTemp);
+
+ if (*lpTemp == 0)
+ return(NULL);
+ else
+ lpTemp++;
+ }
+ else
+ {
+ if (*lpTemp == '%')
+ lpTemp++;
+
+ for (i = 0; i < (fNDS ? NUMVAR : NUMVAR_3X); i++)
+ {
+ if (!nwVarNameCompare(lpTemp, varTable[i].VarName))
+ {
+ lpTemp += strlen(varTable[i].VarName);
+ break;
+ }
+ }
+
+ if (i == (fNDS ? NUMVAR : NUMVAR_3X))
+ return(NULL);
+ }
+
+ return(lpTemp);
+}
+
+/*
+ * Used by EvalSingleCond() in IfHandler()
+ * left part of buffer could be "...", <...>, or ... for variables.
+ * Return TRUE if buffer consists of <left> <compare operator> <right part> +
+ * optional rest parts.
+ * Return FALSE otherwise.
+ */
+int IsCompare (char *buffer, char **ppright,
+ int *pnLeftLen, int *pnRightLen,
+ int *pindex, char **ppRest)
+{
+ int i, nLen;
+ char *lpTemp;
+
+ if ((lpTemp = GetNextPart (buffer)) == NULL)
+ return (FALSE);
+
+ *pnLeftLen = lpTemp-buffer;
+ lpTemp = RemoveSpaces (lpTemp);
+
+ for (i = 0; COMPARE_OPERATORS[i][0]; i++)
+ {
+ nLen = strlen (COMPARE_OPERATORS[i]);
+
+ if (!strncmp(lpTemp, COMPARE_OPERATORS[i], nLen))
+ {
+ *lpTemp = 0;
+ lpTemp += nLen;
+ *ppright = RemoveSpaces (lpTemp);
+ *pindex = i;
+ *ppRest = GetNextPart (*ppright);
+ if ( *ppRest == NULL )
+ return (FALSE);
+ *pnRightLen = *ppRest - *ppright;
+ *ppRest = RemoveSpaces (*ppRest);
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+/*
+ * Used by EvalSingleCond() in IfHandler()
+ * Evaluate lpLeft and lpRight and do the compare operation of index
+ * and put the result in *pfCondition.
+ * Return TRUE if succeed, FALSE otherwise.
+ */
+int Compare (char *lpLeft, char *lpRight,
+ int nLeftLen, int nRightLen,
+ int index, int *pfCondition)
+{
+ char szLeft[MAXLEN], szRight[MAXLEN], *lpTemp;
+ int nCompare, fValue = FALSE;
+
+ if (strncmp (lpLeft, "VALUE", 5) == 0)
+ {
+ fValue = TRUE;
+ lpTemp = RemoveSpaces (lpLeft+5);
+ nLeftLen -= (lpTemp - lpLeft);
+ lpLeft = lpTemp;
+ }
+ if (strncmp (lpRight, "VALUE", 5) == 0)
+ {
+ fValue = TRUE;
+ lpTemp = RemoveSpaces (lpRight+5);
+ nRightLen -= (lpTemp - lpRight);
+ lpRight = lpTemp;
+ }
+
+ strncpy (szLeft, lpLeft, nLeftLen);
+ strncpy (szRight, lpRight, nRightLen);
+
+ szLeft[nLeftLen] = 0;
+ szRight[nRightLen] = 0;
+
+ if (!QuotedStringTranslate (szLeft) ||
+ !QuotedStringTranslate (szRight))
+ return(FALSE);
+
+ if (fValue)
+ nCompare = atoi(szLeft)-atoi(szRight);
+ else
+ nCompare = _stricmp (szLeft, szRight);
+
+ if (IsNotEqual(index))
+ *pfCondition = (nCompare != 0);
+ else if (IsGreaterOrEqual(index))
+ *pfCondition = (nCompare >= 0);
+ else if (IsGreater(index))
+ *pfCondition = (nCompare > 0);
+ else if (IsLessOrEqual(index))
+ *pfCondition = (nCompare <= 0);
+ else if (IsLess(index))
+ *pfCondition = (nCompare < 0);
+ else
+ *pfCondition = (nCompare == 0);
+
+ return(TRUE);
+}
+
+int IsMemberOf (char *buffer)
+{
+ int fIsMemberOf = FALSE;
+
+ if (!strncmp (buffer, "MEMBER", 6))
+ {
+ buffer += 6;
+ if (*buffer == ' ' || *buffer == '\t')
+ {
+ buffer = RemoveSpaces (buffer);
+ if (!strncmp (buffer, "OF", 2))
+ {
+ buffer += 2;
+ if (*buffer == ' ' || *buffer == '\t')
+ buffer = RemoveSpaces (buffer);
+ }
+ }
+
+ fIsMemberOf = (*buffer == '"');
+ }
+
+ return(fIsMemberOf);
+}
+
+int NotMemberOf (char *buffer)
+{
+ int fNotMemberOf = FALSE;
+ if (!strncmp (buffer, "NOT", 3))
+ {
+ buffer += 3;
+ if (*buffer == ' ' || *buffer == '\t')
+ {
+ buffer = RemoveSpaces (buffer);
+ fNotMemberOf = IsMemberOf (buffer);
+ }
+ }
+
+ return(fNotMemberOf);
+}
+
+
+/*
+ * Used by IfHandler()
+ * Evaluate one condition clause and put result in *pfCondition, *ppRest
+ * points to the rest part of buffer.
+ * Return TRUE if succeed, FALSE otherwise.
+ */
+int EvalSingleCond (char *buffer, int *pfCondition)
+{
+ int index, fSuccess = FALSE, nLeftLen, nRightLen;
+ char *pright, *pRest;
+
+ if (IsMemberOf(buffer))
+ fSuccess = MemberOf (buffer, pfCondition, &pRest);
+ else if (NotMemberOf (buffer))
+ {
+ fSuccess = MemberOf (buffer, pfCondition, &pRest);
+ *pfCondition = !(*pfCondition);
+ }
+ else if (IsCompare (buffer, &pright, &nLeftLen, &nRightLen, &index, &pRest))
+ fSuccess = Compare (buffer, pright, nLeftLen, nRightLen, index, pfCondition);
+ else if ( !_strnicmp ("ACCESS_SERVER", buffer, strlen("ACCESS_SERVER")) )
+ {
+ fSuccess = TRUE;
+ *pfCondition = FALSE;
+ pRest = buffer + strlen ("ACCESS_SERVER");
+ }
+
+ if (fSuccess)
+ memmove (buffer, pRest, strlen (pRest)+1);
+
+ return(fSuccess);
+}
+
+int EvaluateCondExpression(char *lpCondExpression, int *pfCondition)
+{
+ int fSuccess = FALSE, fCond;
+ char *lpRight, *lpLeft, *lpOp;
+
+ if (lpRight = strchr (lpCondExpression, ')'))
+ {
+ *lpRight = 0;
+ if ((lpLeft = strrchr (lpCondExpression, '(')) == NULL ||
+ !EvaluateCondExpression(lpLeft+1, pfCondition))
+ return(FALSE);
+
+ *lpLeft = (*pfCondition)? '1' : '0';
+ memmove (lpLeft+1, lpRight+1, strlen (lpRight+1)+1);
+ return(EvaluateCondExpression (lpCondExpression, pfCondition));
+ }
+
+ if (lpOp = strrchr (lpCondExpression, '+'))
+ {
+ *lpOp = 0;
+
+ if (!EvaluateCondExpression (lpCondExpression, pfCondition) ||
+ !EvaluateCondExpression (lpOp+1, &fCond))
+ return(FALSE);
+
+ *pfCondition = (*pfCondition || fCond);
+ return(TRUE);
+ }
+
+ if (lpOp = strrchr (lpCondExpression, '*'))
+ {
+ *lpOp = 0;
+
+ if (!EvaluateCondExpression (lpCondExpression, pfCondition) ||
+ !EvaluateCondExpression (lpOp+1, &fCond))
+ return(FALSE);
+
+ *pfCondition = (*pfCondition && fCond);
+ return(TRUE);
+ }
+
+ if (lpOp = strrchr (lpCondExpression, '^'))
+ {
+ *lpOp = 0;
+
+ if (!EvaluateCondExpression (lpCondExpression, pfCondition) ||
+ !EvaluateCondExpression (lpOp+1, &fCond))
+ return(FALSE);
+
+ *pfCondition = !(*pfCondition && fCond);
+ return(TRUE);
+ }
+
+ if (!strcmp (lpCondExpression, "1"))
+ {
+ *pfCondition = TRUE;
+ return(TRUE);
+ }
+ else if (!strcmp (lpCondExpression, "0"))
+ {
+ *pfCondition = FALSE;
+ return(TRUE);
+ }
+ else
+ return(FALSE);
+}
+
+/*
+ * Used by IfHandler()
+ * Evaluate up to 10 conditions.
+ * Return TRUE if succeed, FALSE otherwise.
+ * On return, buffer stores whatever after conditional expressions
+ * without leading spaces.
+ */
+int EvaluateCond(char *buffer, int *pfCondition)
+{
+ int fCondition = TRUE, fCurrent, fSucceed = FALSE, nCount;
+ char CondExpression[MAXLEN], *lpCond = CondExpression, *lpBuffer = buffer;
+
+ for (nCount = 0; nCount < 10; nCount++)
+ {
+ while (*lpBuffer == '(')
+ {
+ *lpCond = *lpBuffer;
+ lpCond++;
+ lpBuffer++;
+ }
+
+ lpBuffer = RemoveSpaces (lpBuffer);
+
+ if (!EvalSingleCond (lpBuffer, &fCurrent))
+ break;
+
+ *lpCond = fCurrent? '1' : '0';
+ lpCond++;
+
+ while (*lpBuffer == ')')
+ {
+ *lpCond = *lpBuffer;
+ lpCond++;
+ lpBuffer++;
+ }
+
+ lpBuffer = RemoveSpaces (lpBuffer);
+
+ if (*lpBuffer == ',')
+ {
+ *lpCond = '*';
+ lpCond++;
+
+ lpBuffer = RemoveSpaces (lpBuffer+1);
+
+ if (!strncmp (lpBuffer, "AND", 3))
+ lpBuffer = RemoveSpaces (lpBuffer+3);
+ }
+ else if (!strncmp (lpBuffer, "AND", 3))
+ {
+ *lpCond = '*';
+ lpCond++;
+ lpBuffer = RemoveSpaces (lpBuffer+3);
+ }
+ else if (!strncmp (lpBuffer, "&&", 2))
+ {
+ *lpCond = '*';
+ lpCond++;
+ lpBuffer = RemoveSpaces (lpBuffer+2);
+ }
+ else if ( (!strncmp (lpBuffer, "OR", 2)) ||
+ (!strncmp (lpBuffer, "||", 2)) )
+ {
+ *lpCond = '+';
+ lpCond++;
+ lpBuffer = RemoveSpaces (lpBuffer+2);
+ }
+ /*
+ * A NOR expression is documented in some books, but isn't
+ * implemented in the 4X login.exe I have.
+ */
+ else if (!strncmp (lpBuffer, "NOR", 3))
+ {
+ *lpCond = '^';
+ lpCond++;
+ lpBuffer = RemoveSpaces (lpBuffer+3);
+ }
+ else
+ {
+ fSucceed = TRUE;
+ *lpCond = 0;
+ lpBuffer = RemoveSpaces (lpBuffer);
+ memmove (buffer, lpBuffer, strlen (lpBuffer)+1);
+ break;
+ }
+ }
+
+ if (fSucceed)
+ fSucceed = EvaluateCondExpression (CondExpression, pfCondition);
+
+ return(fSucceed);
+}
+
+/*
+ * If statement handler.
+ */
+int IfHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE, fCondition;
+
+ do
+ {
+ if (nCondIndex+1 == MAX_NUM_IF)
+ {
+ DisplayMessage(IDR_IF_TOO_DEEP);
+ fGlobalExitFlag = TRUE;
+ fGlobalIfTooDeep = TRUE;
+ return TRUE;
+ }
+
+ if (EndOfLine (lpParam))
+ break;
+
+ if (!EvaluateCond (lpParam, &fCondition))
+ break;
+
+ if (!strncmp (lpParam, "THEN", 4))
+ {
+ lpParam = RemoveSpaces (lpParam+4);
+
+ if (!strncmp (lpParam, "BEGIN", 5))
+ {
+ lpParam += 5;
+
+ if (!EndOfLine (lpParam))
+ break;
+ }
+ else if((!strncmp (lpParam, "DO", 2)) &&
+ (strncmp (lpParam, "DOS", 3)))
+ {
+ lpParam += 2;
+ if (!EndOfLine (lpParam))
+ break;
+ }
+ }
+ else if (!strncmp (lpParam, "BEGIN", 5))
+ {
+ lpParam += 5;
+
+ if (!EndOfLine (lpParam))
+ break;
+ }
+
+ if (EndOfLine (lpParam))
+ {
+ nCondIndex++;
+ aCondVal[nCondIndex] =
+ (nCondIndex > 0 && !aCondVal[nCondIndex-1])?
+ FALSE : fCondition;
+ }
+ else
+ {
+ if (fCondition && (nCondIndex == -1 || aCondVal[nCondIndex]))
+ CommandDispatch (lpParam);
+ }
+
+ fCommandHandled = TRUE;
+
+ }while (FALSE);
+
+ return(fCommandHandled);
+}
+
+/*
+ * Else statement handler.
+ */
+int ElseHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE;
+
+ if (EndOfLine (lpParam))
+ {
+ if (nCondIndex == 0 ||
+ nCondIndex > 0 && aCondVal[nCondIndex-1])
+ aCondVal[nCondIndex] = !aCondVal[nCondIndex];
+
+ fCommandHandled = TRUE;
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * End statement handler.
+ */
+int EndHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE;
+
+ if (EndOfLine (lpParam))
+ {
+ if (nCondIndex > -1)
+ nCondIndex--;
+
+ fCommandHandled = TRUE;
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * INCLUDE [pathname]filename
+ */
+int IncludeHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE, nFileSize;
+ char *lpLoginScript, *lpTemp;
+ int i, nCondIndexCopy;
+ int aCondValCopy[MAX_NUM_IF];
+ int iRet;
+
+ //
+ // Save off the old globals that track where we are.
+ //
+
+ LABEL_LIST *pLabelList = pGlobalLabelList;
+ char *lpLine = lpGlobalLine;
+ char *lpLineSeparator = lpGlobalLineSeparator;
+ int fHaveNulledLineSeparator = fGlobalHaveNulledLineSeparator;
+
+ pGlobalLabelList = NULL; // so that we don't free it.
+
+ do
+ {
+ if (strtok (lpParam, __SPACES__) == NULL)
+ break;
+
+ lpTemp = strtok(NULL, __SPACES__);
+ if (lpTemp && !EndOfLine (lpTemp))
+ break;
+
+ fCommandHandled = TRUE;
+ NotQuotedStringTranslate(lpParam, TRUE);
+
+ nCondIndexCopy = nCondIndex;
+ for (i = 0; i < MAX_NUM_IF; i++)
+ aCondValCopy[i] = aCondVal[i];
+
+ /*
+ * First we try a NDS object and then a file
+ */
+ iRet = FALSE;
+ if ( fNDS )
+ {
+ iRet = ProcessLoginScriptProperty( lpParam );
+ if ( !iRet )
+ {
+ char Fixup[MAXLEN];
+ char * ptr;
+ /*
+ * Strip off the . in front and add context at end
+ */
+ ptr = RemoveSpaces (lpParam);
+ if ( *ptr == '.' ) {
+ ptr++;
+ strncpy( Fixup, ptr, MAXLEN );
+ }
+ else {
+ strncpy( Fixup, ptr, MAXLEN );
+ if ( Fixup[strlen(Fixup)-1] != '.' )
+ strcat( Fixup, "." );
+ strcat( Fixup, LOGIN_CONTEXT );
+ }
+ iRet = ProcessLoginScriptProperty( Fixup );
+ }
+ }
+
+ if ( !fNDS || !iRet )
+ {
+ nFileSize = NWGetFileSize (lpParam);
+ if (nFileSize == 0)
+ {
+ DisplayMessage(IDR_ERROR_OPEN_SCRIPT, lpParam);
+ break;
+ }
+
+ // user login script exists.
+ lpLoginScript = malloc (nFileSize);
+ if (lpLoginScript == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ break;
+ }
+
+ LoadFile (lpParam, lpLoginScript, nFileSize);
+
+ ProcessLoginScript (lpLoginScript);
+
+ free (lpLoginScript);
+ }
+
+ fGlobalExitFlag = FALSE;
+
+ nCondIndex = nCondIndexCopy;
+ for (i = 0; i < MAX_NUM_IF; i++)
+ aCondVal[i] = aCondValCopy[i];
+
+ }while (FALSE);
+
+ //
+ // restore the globals that track where we are in the file.
+ //
+
+ pGlobalLabelList = pLabelList;
+ lpGlobalLine = lpLine;
+ lpGlobalLineSeparator = lpLineSeparator;
+ fGlobalHaveNulledLineSeparator = fHaveNulledLineSeparator;
+
+
+ return(fCommandHandled);
+}
+
+/*
+ * Map command handler.
+ */
+int MapHandler (char *lpParam)
+{
+ char buffer[MAXLEN]="";
+
+ strcpy( buffer, lpParam );
+
+ NotQuotedStringTranslate( buffer, TRUE );
+
+ Map( buffer );
+
+ return(TRUE);
+}
+
+/*
+ * PAUSE or WAIT.
+ */
+int PauseHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE;
+
+ if (EndOfLine (lpParam))
+ {
+ //Empty kb buffer first.
+ while (_kbhit())
+ _getch();
+
+ DisplayMessage(IDR_STRIKE_KEY);
+ _getch();
+ DisplayMessage(IDR_NEWLINE);
+ fCommandHandled = TRUE;
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * Used by WriteHandler().
+ * Return TRUE if buffer ends with ';'. Set it to 0
+ * Return FALSE otherwise.
+ */
+int EndWithSemicolon (char *buffer)
+{
+ char *lpLastSemicolon, *lpRest;
+ lpLastSemicolon = strrchr (buffer, ';');
+ if (lpLastSemicolon)
+ {
+ lpRest = RemoveSpaces (lpLastSemicolon+1);
+ if (*lpRest == 0)
+ {
+ *lpLastSemicolon = 0;
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+char *ConvertPercent (char *buffer)
+{
+ char *lpPercent, *lpBuffer = buffer;
+ int nPercent = 0;
+
+ while (lpPercent = strchr (lpBuffer, '%'))
+ {
+ nPercent++;
+ lpBuffer = lpPercent+1;
+ }
+
+ if (nPercent == 0)
+ return(NULL);
+
+ lpBuffer = malloc (strlen(buffer)+nPercent+1);
+ if (lpBuffer == NULL)
+ return(NULL);
+
+ strcpy (lpBuffer, buffer);
+
+ lpPercent = strchr (lpBuffer, '%');
+
+ while (lpPercent)
+ {
+ memmove (lpPercent+1, lpPercent, strlen (lpPercent)+1);
+ lpPercent = strchr ( lpPercent+2, '%');
+ }
+
+ return(lpBuffer);
+}
+
+/*
+ * WRITE text, display a text message on the screen.
+ */
+int WriteHandler (char *lpParam)
+{
+ int fNewLine;
+ char *lpBuffer;
+
+ if (*lpParam == 0)
+ {
+ DisplayMessage(IDR_NEWLINE);
+ return(TRUE);
+ }
+
+ fNewLine = !EndWithSemicolon (lpParam);
+
+ if (!QuotedStringTranslate (lpParam))
+ return FALSE;
+
+ lpBuffer = ConvertPercent (lpParam);
+ if (lpBuffer == NULL)
+ {
+ DisplayOemString(lpParam);
+ }
+ else
+ {
+ DisplayOemString(lpBuffer);
+ free (lpBuffer);
+ }
+
+ if (fNewLine)
+ DisplayMessage(IDR_NEWLINE);
+
+ return(TRUE);
+}
+
+/*
+ * Used by ShiftHandler().
+ * Return TURE if the line is all numbers + [comments]
+ * Return FALSE otherwise.
+ */
+int AreAllNumbers(char *buffer)
+{
+ while (isdigit(*buffer))
+ buffer++;
+
+ return(EndOfLine (buffer));
+}
+
+/*
+ * Set the nGlobalShiftDelta variable.
+ */
+int ShiftHandler (char *lpParam)
+{
+ int fCommandHandled = TRUE;
+
+ if (EndOfLine (lpParam))
+ nGlobalShiftDelta++;
+ else if (*lpParam == '-')
+ {
+ lpParam = RemoveSpaces (lpParam+1);
+ if (!AreAllNumbers(lpParam))
+ fCommandHandled = FALSE;
+ else
+ nGlobalShiftDelta -= atoi (lpParam);
+ }
+ else
+ {
+ if (*lpParam == '+')
+ lpParam = RemoveSpaces (lpParam+1);
+
+ if (!AreAllNumbers(lpParam))
+ fCommandHandled = FALSE;
+ else
+ nGlobalShiftDelta += atoi (lpParam);
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * Set the machine name.
+ */
+int MachineHandler (char *lpParam)
+{
+ int nLen, i;
+
+ if (*lpParam != '=')
+ return(FALSE);
+
+ lpParam = RemoveSpaces (lpParam+1);
+ if (!QuotedStringTranslate(lpParam))
+ return(FALSE);
+
+ nLen = strlen (lpParam);
+ for (i = nLen; i < 15; i++)
+ *(lpParam+i) = ' ';
+
+ *(lpParam+15) = 0;
+
+ return(TRUE);
+}
+
+/*
+ * Set the fGlobalCompatible variable.
+ */
+int CompatibleHandler(char *lpParam)
+{
+ if (!EndOfLine (lpParam))
+ return(FALSE);
+
+ fGlobalCompatible = TRUE;
+ return(TRUE);
+}
+
+/*
+ * Clear the screen
+ */
+int ClearHandler(char *lpParam)
+{
+ CONSOLE_SCREEN_BUFFER_INFO coninfo;
+ COORD scrolltarget;
+ CHAR_INFO chinfo;
+ SMALL_RECT scrollrect;
+
+ if ( hconout == INVALID_HANDLE_VALUE )
+ {
+ hconout = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, 0, NULL );
+ }
+
+ if ( hconout == INVALID_HANDLE_VALUE )
+ return TRUE;
+
+ GetConsoleScreenBufferInfo( hconout, &coninfo );
+
+ scrolltarget.Y = (SHORT)(0 - coninfo.dwSize.Y);
+ scrolltarget.X = 0;
+
+ scrollrect.Top = 0;
+ scrollrect.Left = 0;
+ scrollrect.Bottom = coninfo.dwSize.Y;
+ scrollrect.Right = coninfo.dwSize.X;
+ chinfo.Char.AsciiChar = ' ';
+ chinfo.Attributes = coninfo.wAttributes;
+ ScrollConsoleScreenBufferA( hconout, &scrollrect, NULL,
+ scrolltarget, &chinfo);
+
+ coninfo.dwCursorPosition.X = 0;
+ coninfo.dwCursorPosition.Y = 0;
+
+ SetConsoleCursorPosition( hconout, coninfo.dwCursorPosition );
+ return(TRUE);
+}
+
+/*
+ * Display the Last Login Time
+ */
+int LastLoginTimeHandler(char *lpParam)
+{
+ BYTE dataBuffer[128];
+ unsigned char moreFlag;
+ unsigned char propertyType;
+
+ if ( fNDS )
+ {
+ nwShowLastLoginTime();
+ }
+ else
+ {
+ NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "MISC_LOGIN_INFO",
+ 1,
+ dataBuffer,
+ &moreFlag,
+ &propertyType);
+ /*
+ * 0 = year
+ * 1 = month
+ * 2 = day
+ * 3 = hour
+ * 4 = minute
+ * 5 = second
+ */
+
+ if ( dataBuffer[3] >= 12 )
+ {
+ DisplayMessage( IDR_LASTLOGIN_PM,
+ dataBuffer[1],
+ dataBuffer[2],
+ dataBuffer[0],
+ dataBuffer[3] - 12,
+ dataBuffer[4],
+ dataBuffer[5] );
+ }
+ else
+ {
+ DisplayMessage( IDR_LASTLOGIN_AM,
+ dataBuffer[1],
+ dataBuffer[2],
+ dataBuffer[0],
+ dataBuffer[3],
+ dataBuffer[4],
+ dataBuffer[5] );
+ }
+ }
+
+ return(TRUE);
+}
+
+
+
+/*
+ * Change and/or display the current context.
+ */
+int ContextHandler (char *lpParam)
+{
+ unsigned char Buffer[MAXLEN];
+ unsigned char * ptr;
+ unsigned char CurrentContext[MAXLEN];
+
+ if ( *lpParam )
+ {
+ NotQuotedStringTranslate(lpParam, TRUE);
+
+ ptr = RemoveSpaces (lpParam);
+
+ if ( NDSCanonicalizeName( lpParam, Buffer, MAXLEN, TRUE ) )
+ {
+ DisplayMessage(IDR_CHANGE_CONTEXT_ERROR, lpParam);
+ return(TRUE);
+ }
+
+ if ( NDSChangeContext( Buffer ) )
+ {
+ DisplayMessage(IDR_CHANGE_CONTEXT_ERROR, lpParam);
+ return(TRUE);
+ }
+ }
+
+ if ( NDSGetContext( CurrentContext, MAXLEN ) )
+ {
+ DisplayMessage(IDR_GET_CONTEXT_ERROR);
+ }
+ else
+ {
+ DisplayMessage(IDR_DISPLAY_CONTEXT, CurrentContext);
+ }
+ return(TRUE);
+}
+
+/*
+ * Do nothing. Return TRUE so the the command will not
+ * be considered as bad.
+ */
+int ScriptServerHandler (char *lpParam)
+{
+ return(TRUE);
+}
+
+/*
+ * If this is a 4X login, do not execute the default login script.
+ */
+int NoDefaultHandler (char *lpParam)
+{
+ if ( fNDS )
+ fNoDefaultLoginScript = TRUE;
+ return(TRUE);
+}
+
+/*
+ * Do nothing. Return TRUE so the the command will not
+ * be considered as bad.
+ */
+int NullHandler (char *lpParam)
+{
+ return(TRUE);
+}
+
+#define NUMBER_ARGUMENTS 20
+
+/*
+ * External commands start with '#', such as #command /c cls
+ */
+void ExternalCmdHandler (char *lpCommand)
+{
+ int n;
+ int i;
+ unsigned int CommandLength;
+ char *lpCmdName, *argv[NUMBER_ARGUMENTS];
+
+ for ( n = 0; n < NUMBER_ARGUMENTS; n++ )
+ argv[n] = NULL;
+
+ if ((nCondIndex == -1) || aCondVal[nCondIndex])
+ {
+ //Convert variables first.
+ NotQuotedStringTranslate(lpCommand, FALSE);
+
+ lpCommand = RemoveSpaces(lpCommand+1);
+ lpCmdName = strtok (lpCommand, __SPACES__);
+
+ lpCmdName = NTNWtoUNCFormat(lpCmdName);
+
+ argv[0] = lpCmdName;
+
+ for (n = 1; n < NUMBER_ARGUMENTS - 1; n++)
+ {
+ if ((argv[n] = strtok (NULL, __SPACES__)) == NULL)
+ break;
+ }
+
+ argv[9] = NULL;
+
+ /*
+ * Capture command
+ */
+ CommandLength = strlen( lpCommand );
+
+ /*
+ * First see if a COMMAND.COM is invoked
+ */
+ if ( ( ( CommandLength >= strlen("COMMAND.COM") ) &&
+ ( !_stricmp( &lpCommand[CommandLength-strlen("COMMAND.COM")], "COMMAND.COM") ) ) ||
+ ( ( CommandLength >= strlen("COMMAND") ) &&
+ ( !_stricmp( &lpCommand[CommandLength-strlen("COMMAND")], "COMMAND") ) ) )
+ {
+ /*
+ * Search for the CAPTURE argument
+ */
+ for ( i = 1; i < n; i++ )
+ {
+ CommandLength = strlen( argv[i] );
+ if ( ( ( CommandLength >= strlen("CAPTURE.EXE") ) &&
+ ( !_stricmp( &(argv[i])[CommandLength-strlen("CAPTURE.EXE")], "CAPTURE.EXE") ) ) ||
+ ( ( CommandLength >= strlen("CAPTURE") ) &&
+ ( !_stricmp( &(argv[i])[CommandLength-strlen("CAPTURE")], "CAPTURE") ) ) ) {
+ Capture( argv + i, n - i );
+ return;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Is this a CAPTURE command?
+ */
+ if ( ( ( CommandLength >= strlen("CAPTURE.EXE") ) &&
+ ( !_stricmp( &lpCommand[CommandLength-strlen("CAPTURE.EXE")], "CAPTURE.EXE") ) ) ||
+ ( ( CommandLength >= strlen("CAPTURE") ) &&
+ ( !_stricmp( &lpCommand[CommandLength-strlen("CAPTURE")], "CAPTURE") ) ) ) {
+ Capture( argv, n );
+ return;
+ }
+ }
+
+ if ((SCRIPT_ERROR = _spawnvp (P_WAIT, lpCmdName, argv)) == -1)
+ {
+ if (errno == ENOENT)
+ DisplayMessage(IDR_ENOENT, lpCommand);
+ else
+ DisplayMessage(IDR_CANNOT_EXECUTE, lpCommand);
+ }
+ }
+}
+
+/*
+ * Printe out the bad command line.
+ */
+void BadCommandHandler (char *lpCommand)
+{
+ DisplayMessage(IDR_SCRIPT_ERROR);
+ DisplayMessage(IDR_ORIGINAL_LINE_WAS, lpCommand);
+}
+
+
+/*
+ * Swap the object id.
+ */
+DWORD SwapLong(DWORD number)
+{
+ BYTE *p, tmp[4];
+
+ p = (BYTE *)&number;
+
+ tmp[0] = p[3];
+ tmp[1] = p[2];
+ tmp[2] = p[1];
+ tmp[3] = p[0];
+
+ return(*(DWORD *)tmp);
+}
+
+/*
+ * Remove leading spaces, including tabs.
+ */
+char *RemoveSpaces (char * buffer)
+{
+ while (*buffer == ' ' || *buffer == '\t')
+ buffer++;
+ return(buffer);
+}
+
+/*
+ * Return TRUE if buffer points to the end of the lind, FALSE otherwise.
+ */
+int EndOfLine (char *buffer)
+{
+ int fEndOfLine = FALSE;
+
+ buffer = RemoveSpaces (buffer);
+
+ if (*buffer == '\0' ||
+ *buffer == ';' ||
+ *buffer == '*' ||
+ *buffer == '\r')
+ fEndOfLine = TRUE;
+
+ return(fEndOfLine);
+}
+
+/*
+ * Return TRUE if lpParam points to "ON", FALSE otherwise.
+ */
+int IsOn (char *lpParam)
+{
+ int fOn = FALSE;
+
+ if (!strncmp (lpParam, "ON", 2))
+ {
+ lpParam += 2;
+ fOn = EndOfLine (lpParam);
+ }
+
+ return(fOn);
+}
+
+/*
+ * Return TRUE if lpParam points to "OFF", FALSE otherwise.
+ */
+int IsOff (char *lpParam)
+{
+ int fOff = FALSE;
+
+ if (!strncmp (lpParam, "OFF", 3))
+ {
+ lpParam += 3;
+ fOff = EndOfLine (lpParam);
+ }
+
+ return(fOff);
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the value of time variable specified by index.
+ */
+void GetTime (char *buffer, int index)
+{
+ time_t currentTime;
+ struct tm *tmCurrentTime;
+
+ time (&currentTime);
+ tmCurrentTime = localtime(&currentTime);
+
+ switch (index)
+ {
+ case IDS_DAY:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_mday);
+ break;
+ case IDS_DAY_OF_WEEK:
+ strcpy (buffer, __Day__[tmCurrentTime->tm_wday]);
+ break;
+ case IDS_MONTH:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_mon+1);
+ break;
+ case IDS_MONTH_NAME:
+ strcpy (buffer, __Month__[tmCurrentTime->tm_mon]);
+ break;
+ case IDS_NDAY_OF_WEEK:
+ sprintf (buffer, "%d\0", tmCurrentTime->tm_wday+1);
+ break;
+ case IDS_SHORT_YEAR:
+ sprintf (buffer, "%04d\0", tmCurrentTime->tm_year+1900);
+ strcpy (buffer, buffer+2);
+ break;
+ case IDS_YEAR:
+ sprintf (buffer, "%04d\0", tmCurrentTime->tm_year+1900);
+ break;
+ case IDS_AM_PM:
+ strcpy (buffer, __AMPM__[tmCurrentTime->tm_hour > 12? 1:0]);
+ break;
+ case IDS_GREETING_TIME:
+ if (tmCurrentTime->tm_hour >= 6 && tmCurrentTime->tm_hour < 12)
+ index=0;
+ else if (tmCurrentTime->tm_hour >= 12 && tmCurrentTime->tm_hour < 18)
+ index=1;
+ else
+ index=2;
+
+ strcpy (buffer, __GREETING__[index]);
+ break;
+ case IDS_HOUR:
+ if (tmCurrentTime->tm_hour > 12)
+ tmCurrentTime->tm_hour -= 12;
+ sprintf (buffer, "%d\0", tmCurrentTime->tm_hour);
+ break;
+ case IDS_HOUR24:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_hour);
+ break;
+ case IDS_MINUTE:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_min);
+ break;
+ case IDS_SECOND:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_sec);
+ break;
+ default:
+ *buffer = 0;
+ }
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer login user's full name.
+ */
+void GetFullName (char *buffer)
+{
+ unsigned int iRet = 0;
+ unsigned char moreFlag;
+ unsigned char propertyType;
+
+ if ( fNDS )
+ {
+ NDSGetVar ( "Full Name", buffer, 128 );
+ if ( buffer[0] == '\0' )
+ strcpy (buffer, "* Unknown *");
+ }
+ else
+ {
+ iRet = NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "IDENTIFICATION",
+ 1,
+ buffer,
+ &moreFlag,
+ &propertyType);
+ if (iRet)
+ strcpy (buffer, "* Unknown *");
+ }
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer login user's object id.
+ */
+void GetUserID (char *buffer)
+{
+ unsigned long dwObjectID = 0;
+
+ if ( fNDS )
+ dwObjectID = GUserObjectID;
+ else
+ NTGetUserID( CONNECTION_ID, &dwObjectID );
+ sprintf (buffer, "%lx\0", SwapLong(dwObjectID));
+ _strupr (buffer);
+}
+
+unsigned int GetDays (unsigned int year, BYTE month, BYTE date)
+{
+ unsigned int i, days = 0;
+
+ for (i = 1; i < month; i++)
+ {
+ if (i == 2)
+ days += (year%4)? 28 : 29;
+ else if (i == 4 || i == 6 || i == 9 || i == 11)
+ days += 30;
+ else
+ days += 31;
+ }
+
+ days += date;
+ return(days);
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the days in which the password expires.
+ */
+void GetPasswordExpires (char *buffer)
+{
+ unsigned int iRet = 0;
+ unsigned int iRet2 = 0;
+ unsigned char moreFlag;
+ unsigned int yearCurrent, yearEnd, days;
+ BYTE monthCurrent, dayCurrent, monthEnd, dayEnd;
+ unsigned int exptime, logintime;
+ unsigned char propertyType;
+
+
+ if ( fNDS )
+ {
+ iRet = NDSGetUserProperty ("Password Expiration Time", (PBYTE)&exptime,
+ 4, NULL, NULL);
+ iRet2 = NDSGetUserProperty ("Login Time", (PBYTE)&logintime,
+ 4, NULL, NULL);
+
+ if ( ( exptime && logintime ) && !iRet && !iRet2 )
+ {
+ if ( exptime <= logintime )
+ strcpy( buffer, "0" );
+ else
+ sprintf( buffer, "%u", ((exptime-logintime)/(60*60*24)) + 1 );
+ }
+ else
+ {
+ sprintf( buffer, "%u", 0x7FFF );
+ }
+ }
+ else
+ {
+ NTGetTheDate( &yearCurrent, &monthCurrent, &dayCurrent );
+ NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "LOGIN_CONTROL",
+ 1,
+ buffer,
+ &moreFlag,
+ &propertyType);
+
+ yearEnd = 1900 + buffer[4];
+ monthEnd = buffer[5];
+ dayEnd = buffer[6];
+
+ if (monthEnd == 0)
+ days = (((yearCurrent%4)? 365 : 366) - GetDays (yearCurrent, monthCurrent, dayCurrent));
+ else if (yearEnd == yearCurrent)
+ {
+ if (monthEnd < monthCurrent ||
+ (monthEnd == monthCurrent && dayEnd <= dayCurrent))
+ days = 0;
+ else
+ days = GetDays (yearEnd, monthEnd, dayEnd) - GetDays (yearCurrent, monthCurrent, dayCurrent) - 1;
+ }
+ else
+ days = ((yearCurrent%4)? 364 : 365) + GetDays (yearEnd, monthEnd, dayEnd) - GetDays (yearCurrent, monthCurrent, dayCurrent);
+
+ sprintf (buffer, "%u", days);
+ }
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer value of the dos environment variable.
+ * If the variable is not found, buffer is set to be empty string.
+ */
+void GetDosEnv (char *buffer)
+{
+ char *lpTemp;
+
+ // This could be called from "%<x>" where x is not upcase. capitalize
+ // the string first to be sure.
+ _strupr(buffer);
+
+ lpTemp = strchr (buffer, '>');
+ *lpTemp = 0;
+
+ lpTemp = getenv (buffer+1);
+
+ if (lpTemp && strlen (lpTemp) < MAXLEN )
+ strcpy (buffer, lpTemp);
+ else
+ *buffer = 0;
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the 8 bytes network address.
+ */
+void GetNetWorkAddr (char *buffer)
+{
+ unsigned char internetAddress[10];
+
+ GetInternetAddress (CONNECTION_ID,
+ CONNECTION_NUMBER,
+ internetAddress);
+
+ sprintf (buffer,
+ "%02X%02X%02X%02X\0",
+ internetAddress[0],
+ internetAddress[1],
+ internetAddress[2],
+ internetAddress[3] );
+}
+
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the 12 bytes node address to buffer.
+ */
+void GetPStation (char *buffer)
+{
+ unsigned char internetAddress[10];
+
+ GetInternetAddress (CONNECTION_ID,
+ CONNECTION_NUMBER,
+ internetAddress);
+
+ sprintf (buffer,
+ "%02X%02X%02X%02X%02X%02X\0",
+ internetAddress[4],
+ internetAddress[5],
+ internetAddress[6],
+ internetAddress[7],
+ internetAddress[8],
+ internetAddress[9]);
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the decimal string representing the remaining account
+ * balance
+ */
+void GetAccountBalance (char *buffer)
+{
+ DWORD balance;
+ BYTE dataBuffer[128];
+ unsigned char moreFlag;
+ unsigned char propertyType;
+ unsigned int err;
+
+ if ( fNDS )
+ {
+ err = NDSGetUserProperty ("Account Balance", dataBuffer,128, NULL, NULL);
+ }
+ else
+ {
+ err = NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "ACCOUNT_BALANCE",
+ 1,
+ dataBuffer,
+ &moreFlag,
+ &propertyType);
+ }
+
+ if ( err )
+ balance = 0;
+ else
+ balance = *((DWORD *)dataBuffer);
+
+ sprintf (buffer, "%d", balance);
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer MACHINE, SMACHINE, OS, OS_VERSION or SHELL_TYPE
+ * to buffer according to index.
+ */
+void GetShellVersion(char *buffer, int index)
+{
+ static char szTemp[40];
+ char *lpTemp;
+ BYTE shellmajor, shellminor, shellnum;
+
+ NTGetVersionOfShell( szTemp, &shellmajor, &shellminor, &shellnum );
+
+ lpTemp = szTemp;
+
+ switch (index)
+ {
+ case IDS_OS:
+ strcpy (buffer, lpTemp);
+ break;
+ case IDS_OS_VERSION:
+ lpTemp += (strlen (lpTemp)+1);
+ strcpy (buffer, lpTemp);
+ break;
+ case IDS_MACHINE:
+ lpTemp += (strlen (lpTemp)+1);
+ lpTemp += (strlen (lpTemp)+1);
+ strcpy (buffer, lpTemp);
+ break;
+ case IDS_SMACHINE:
+ lpTemp += (strlen (lpTemp)+1);
+ lpTemp += (strlen (lpTemp)+1);
+ lpTemp += (strlen (lpTemp)+1);
+ strcpy (buffer, lpTemp);
+ break;
+ case IDS_SHELL_TYPE:
+ case IDS_SHELL_VERSION:
+ sprintf (buffer, "V%d.%d%d%c", shellmajor, shellminor/10, shellminor%10, 'A'+shellnum);
+ break;
+ default:
+ *buffer = 0;
+ break;
+ }
+}
+
+void GetArgv(char *buffer)
+{
+ int n;
+
+ n = atoi (buffer)+nGlobalShiftDelta;
+
+ if (n == 0)
+ strcpy (buffer, PREFERRED_SERVER);
+ else if (n == 1)
+ strcpy (buffer, LOGIN_NAME);
+ else if (n > 1 && n < ARGC)
+ strcpy (buffer, ARGV[n]);
+ else
+ *buffer = 0;
+}
+
+/*
+ * vartext is an array of size MAXLEN.
+ * vartext points to a string starts with a variable on enter.
+ * vartext stores the value of the variable on exit.
+ * Return the lenth of the variable.
+ */
+int VarTranslate(char *vartext)
+{
+ int i, nVarLen = 0;
+
+ for (i = 0; i < (fNDS ? NUMVAR : NUMVAR_3X); i++)
+ {
+ if (!nwVarNameCompare(vartext, varTable[i].VarName))
+ {
+ nVarLen = strlen(varTable[i].VarName);
+
+ switch ( i )
+ {
+ case IDS_DAY_OF_WEEK:
+ case IDS_DAY:
+ case IDS_MONTH_NAME:
+ case IDS_MONTH:
+ case IDS_NDAY_OF_WEEK:
+ case IDS_SHORT_YEAR:
+ case IDS_YEAR:
+ case IDS_AM_PM:
+ case IDS_GREETING_TIME:
+ case IDS_HOUR24:
+ case IDS_HOUR:
+ case IDS_MINUTE:
+ case IDS_SECOND:
+ GetTime (vartext, i);
+ break;
+ case IDS_FULL_NAME:
+ GetFullName (vartext);
+ break;
+ case IDS_LOGIN_NAME:
+ strcpy (vartext, LOGIN_NAME);
+ /*
+ * 4X LOGIN.EXE always truncates and replaces spaces
+ * with underscores. There was a report that some
+ * versions of 3X LOGIN.EXE do this also.
+ */
+ if ( fNDS )
+ {
+ int i;
+ vartext[8] = '\0';
+ for ( i = 0; i < 8; i++ )
+ if ( vartext[i] == ' ' )
+ vartext[i] = '_';
+ }
+ break;
+ case IDS_USER_ID:
+ GetUserID (vartext);
+ break;
+ case IDS_PASSWORD_EXPIRES:
+ GetPasswordExpires (vartext);
+ break;
+ case IDS_NETWORK_ADDRESS:
+ case IDS_NETWORK:
+ GetNetWorkAddr (vartext);
+ break;
+ case IDS_FILE_SERVER:
+ strcpy (vartext, PREFERRED_SERVER);
+ break;
+ case IDS_ACCESS_SERVER:
+ case IDS_ACCESS:
+ strcpy (vartext, "0");
+ break;
+ case IDS_ERROR_LEVEL:
+ case IDS_ERRORLEVEL:
+ sprintf (vartext, "%u", SCRIPT_ERROR);
+ break;
+ case IDS_MACHINE:
+ case IDS_OS_VERSION:
+ case IDS_OS:
+ case IDS_SMACHINE:
+ case IDS_SHELL_TYPE:
+ case IDS_SHELL_VERSION:
+ GetShellVersion (vartext, i);
+ break;
+ case IDS_STATION:
+ sprintf (vartext, "%d", CONNECTION_NUMBER);
+ break;
+ case IDS_P_STATION:
+ GetPStation (vartext);
+ break;
+ case IDS_LAST_NAME:
+ case IDS_SURNAME:
+ strcpy (vartext, LAST_NAME);
+ break;
+ case IDS_LOGIN_CONTEXT:
+ strcpy (vartext, LOGIN_CONTEXT);
+ break;
+ case IDS_NETWARE_REQUESTER:
+ case IDS_REQUESTER_VERSION:
+ case IDS_DOS_REQUESTER:
+ case IDS_REQUESTER:
+ strcpy (vartext, REQUESTER_VERSION);
+ break;
+ case IDS_REQUESTER_CONTEXT:
+ strcpy (vartext, REQUESTER_CONTEXT);
+ break;
+ case IDS_ACCOUNT_BALANCE:
+ GetAccountBalance (vartext);
+ break;
+ case IDS_CN:
+ strcpy (vartext, COMMON_NAME);
+ break;
+ case IDS_HOME_DIRECTORY:
+ {
+ char buffer[MAXLEN];
+
+ vartext[0] = '\0';
+ NDSGetVar ( varTable[i].VarName, buffer, MAXLEN );
+ if ( buffer[0] )
+ ConverNDSPathToNetWarePathA( buffer, NULL, vartext );
+ }
+ break;
+ case IDS_ADMINISTRATIVE_ASSISTANT:
+ case IDS_ALLOW_UNLIMITED_CREDIT:
+ case IDS_DESCRIPTION:
+ case IDS_EMAIL_ADDRESS:
+ case IDS_EMPLOYEE_ID:
+ case IDS_FACSIMILE_TELEPHONE_NUMBER:
+ case IDS_GROUP_MEMBERSHIP:
+ case IDS_HIGHER_PRIVILEGES:
+ case IDS_INITIALS:
+ case IDS_LANGUAGE:
+ case IDS_LOCKED_BY_INTRUDER:
+ case IDS_LOGIN_DISABLED:
+ case IDS_LOGIN_GRACE_LIMIT:
+ case IDS_LOGIN_GRACE_REMAINING:
+ case IDS_LOGIN_INTRUDER_ATTEMPTS:
+ case IDS_LOGIN_MAXIMUM_SIMULTANEOUS:
+ case IDS_MAILSTOP:
+ case IDS_MESSAGE_SERVER:
+ case IDS_MINIMUM_ACCOUNT_BALANCE:
+ case IDS_OBJECT_CLASS:
+ case IDS_OU:
+ case IDS_PASSWORD_ALLOW_CHANGE:
+ case IDS_PASSWORD_MINIMUM_LENGTH:
+ case IDS_PASSWORD_REQUIRED:
+ case IDS_PASSWORD_UNIQUE_REQUIRED:
+ case IDS_PASSWORDS_USED:
+ case IDS_PHYSICAL_DELIVERY_OFFICE_NAME:
+ case IDS_POSTAL_ADDRESS:
+ case IDS_POSTAL_CODE:
+ case IDS_POSTAL_OFFICE_BOX:
+ case IDS_PRIVATE_KEY:
+ case IDS_PROFILE:
+ case IDS_REVISION:
+ case IDS_SECURITY_EQUALS:
+ case IDS_SECURITY_FLAGS:
+ case IDS_SEE_ALSO:
+ case IDS_SERVER_HOLDS:
+ case IDS_SUPERVISOR:
+ case IDS_TELEPHONE_NUMBER:
+ case IDS_TITLE:
+ case IDS_CERTIFICATE_VALIDITY_INTERVAL:
+ case IDS_EQUIVALENT_TO_ME:
+ case IDS_GENERATIONAL_QUALIFIER:
+ case IDS_GIVEN_NAME:
+ case IDS_MAILBOX_ID:
+ case IDS_MAILBOX_LOCATION:
+ case IDS_PROFILE_MEMBERSHIP:
+ case IDS_SA:
+ case IDS_S:
+ case IDS_L:
+ NDSGetVar ( varTable[i].VarName, vartext, MAXLEN );
+ break;
+ }
+ return(nVarLen);
+ }
+ }
+
+ if (isdigit(*vartext))
+ {
+ while (isdigit(vartext[nVarLen]))
+ nVarLen++;
+ GetArgv(vartext);
+ }
+ else if (*vartext == '<')
+ {
+ nVarLen = 1;
+ while (vartext[nVarLen] != '>' && vartext[nVarLen] != 0)
+ {
+ if (IsDBCSLeadByte(vartext[nVarLen]))
+ nVarLen++;
+ nVarLen++;
+ }
+
+ if (vartext[nVarLen] == 0)
+ nVarLen = 0;
+ else
+ {
+ nVarLen++;
+ GetDosEnv (vartext);
+ }
+ }
+
+ return(nVarLen);
+}
+
+/*
+ * Parse path string.
+ * If find the %variable value, replace it, otherwise keep as it is.
+ */
+void NotQuotedStringTranslate(char *buf, BOOL Remove_dbs)
+{
+ char *pPercentSign, *pRest, vartext[MAXLEN];
+ int nVarLen, nInsertlen;
+
+ if ( Remove_dbs )
+ {
+ // Convert \\ to \.
+ pRest = buf;
+ for (pRest = buf; *pRest; pRest = NWAnsiNext(pRest))
+ {
+ if (*pRest == '\\' && *(pRest+1) == '\\')
+ memmove (pRest, pRest+1, strlen (pRest));
+ }
+ }
+
+ // Convert variables following '%' sign.
+ pRest = buf;
+ while (pPercentSign = strchr(pRest, '%'))
+ {
+ pRest = pPercentSign+1;
+
+ strcpy (vartext, pRest);
+
+ nVarLen = VarTranslate(vartext);
+
+ if (nVarLen == 0)
+ continue;
+
+ nInsertlen = strlen (vartext);
+ if (strlen (buf) + nInsertlen - nVarLen < MAXLEN)
+ {
+ pRest = pPercentSign+1+nVarLen;
+
+ memmove (pPercentSign+nInsertlen, pRest, strlen (pRest)+1);
+ memmove (pPercentSign, vartext, nInsertlen);
+ pRest = pPercentSign+nInsertlen;
+ }
+ }
+}
+
+/*
+ * Used by QuotedStringTranslate()
+ * On enter, *ppTemp point to a variable, on exit *ppTemp points to the
+ * charecter next to the variable. *ppBuffer points to the end of the
+ * value of the variable.
+ */
+int DoVarTranslate (char **ppTemp, char **ppBuffer, unsigned int nMaxLen, int fInquotes)
+{
+ int nVarLen;
+ char vartext[MAXLEN];
+
+ strcpy (vartext, *ppTemp);
+
+ nVarLen = VarTranslate (vartext);
+
+ if (nVarLen != 0)
+ {
+ if (strlen(vartext) >= nMaxLen)
+ return(FALSE);
+
+ strcpy (*ppBuffer, vartext);
+ (*ppBuffer) = (*ppBuffer) + strlen (vartext);
+ (*ppTemp) += nVarLen;
+ }
+ else if (fInquotes)
+ {
+ strcpy (*ppBuffer, "%");
+ (*ppBuffer) += 1;
+ }
+ else
+ return(FALSE);
+
+ return(TRUE);
+}
+
+/*
+ * Used by QuotedStringTranslate()
+ * On entry, *(*ppTemp -1) is '\', if **ppTemp is one of those special
+ * characters, put the value in **ppBuffer, otherwise copy '\\\ and
+ * whatever is in *ppBuffer to *ppBuffer.
+ */
+void TranslateSpecialChar (char **ppTemp, char **ppBuffer)
+{
+ (*ppTemp)++;
+
+ if (**ppTemp == '\\')
+ **(ppBuffer) = '\\';
+ else if (**ppTemp == 'n')
+ **(ppBuffer) ='\n';
+ else if (**ppTemp == 'r')
+ **(ppBuffer) ='\r';
+ else if (**ppTemp == '\"')
+ **(ppBuffer) ='\"';
+ else if (**ppTemp == '7')
+ **(ppBuffer) ='\7';
+ else
+ {
+ **(ppBuffer) = '\\';
+ (*ppBuffer)++;
+ return;
+ }
+
+ (*ppBuffer)++;
+ (*ppTemp)++;;
+}
+
+/*
+ * Used by QuotedStringTranslate().
+ * Return TRUE if there are more interesting strings and it's seperated by ';'
+ * FALSE otherwise.
+ */
+int GetNextString (char **ppTemp, int *pfEnd)
+{
+ int fMore = FALSE;
+
+ (*ppTemp) = RemoveSpaces (*ppTemp);
+
+ *pfEnd = (**ppTemp == 0);
+
+ if (**ppTemp == ';')
+ {
+ (*ppTemp) = RemoveSpaces (*ppTemp+1);
+ fMore = TRUE;
+ }
+
+ return(fMore);
+}
+
+
+int GetLastShiftOp (char *buffer, char *pchOp, char *lpRest)
+{
+ int i, inquotes = FALSE;
+
+ // NetWare compatibility fix.
+ // for (i = strlen (buffer)-1; i >= 0; i--)
+
+ for (i = 0; buffer[i]; i++)
+ {
+ if (buffer[i] == '\"' && buffer [i-1] != '\\')
+ inquotes = !inquotes;
+ if (!inquotes &&
+ ( (buffer[i] == '>' && buffer[i+1] == '>')
+ ||(buffer[i] == '<' && buffer[i+1] == '<')))
+ {
+ *pchOp = buffer[i];
+ buffer[i] = 0;
+ strcpy (lpRest, RemoveSpaces(buffer+i+2));
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+int GetLastAddOp (char *buffer, char *pchOp, char *lpRest)
+{
+ int i, inquotes = FALSE;
+
+ // NetWare compatibility fix.
+ // for (i = strlen (buffer)-1; i >= 0; i--)
+
+ for (i = 0; buffer[i]; i++)
+ {
+ if (buffer[i] == '\"' && buffer [i-1] != '\\')
+ inquotes = !inquotes;
+ if (!inquotes &&
+ (buffer[i] == '+' || buffer[i] == '-') )
+ {
+ *pchOp = buffer[i];
+ buffer[i] = 0;
+ strcpy (lpRest, RemoveSpaces(buffer+i+1));
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+int GetLastMultiplyOp (char *buffer, char *pchOp, char *lpRest)
+{
+ int i, inquotes = FALSE;
+
+ // NetWare compatibility fix.
+ // for (i = strlen (buffer)-1; i >= 0; i--)
+ for (i = 0; buffer[i]; i++)
+ {
+ if (buffer[i] == '\"' && buffer [i-1] != '\\')
+ inquotes = !inquotes;
+ if (!inquotes &&
+ (buffer[i] == '*' || buffer[i] == '/' || buffer[i] == '%') )
+ {
+
+ *pchOp = buffer[i];
+ buffer[i] = 0;
+ strcpy (lpRest, RemoveSpaces(buffer+i+1));
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+/*
+ * Used by QuotedStringTranslate.
+ * Return TRUE if input buffer is right format, FALSE otherwise.
+ */
+int SingleStringTranslate (char *buffer)
+{
+ int inquotes = FALSE, fEnd = FALSE, nShift, nLen;
+ char szRest[MAXLEN], chOp;
+ char *lpTemp = szRest, *lpBuffer=buffer;
+
+ buffer = RemoveSpaces (buffer);
+
+ if (GetLastShiftOp (buffer, &chOp, szRest))
+ {
+ if (!QuotedStringTranslate (buffer))
+ return(FALSE);
+
+ while (isdigit (*lpTemp))
+ lpTemp++;
+
+ if (!EndOfLine(lpTemp))
+ return(FALSE);
+
+ *lpTemp = 0;
+
+ nShift = atoi (szRest);
+ nLen = strlen (buffer);
+
+ if (nShift >= nLen)
+ *buffer = 0;
+ else
+ {
+ if (chOp == '<')
+ memmove (buffer, buffer+nShift, nLen-nShift);
+
+ *(buffer+nLen-nShift) = 0;
+ }
+ }
+ else if (GetLastAddOp (buffer, &chOp, szRest))
+ {
+ if (!QuotedStringTranslate (buffer) ||
+ !QuotedStringTranslate (szRest))
+ return(FALSE);
+
+ sprintf (buffer, "%d", (chOp == '+')? (atoi (buffer) + atoi (szRest))
+ : (atoi (buffer) - atoi (szRest)));
+ }
+ else if (GetLastMultiplyOp (buffer, &chOp, szRest))
+ {
+ if (!QuotedStringTranslate (buffer) ||
+ !QuotedStringTranslate (szRest))
+ return(FALSE);
+
+ if (chOp == '*')
+ sprintf (buffer, "%d", atoi (buffer) * atoi (szRest));
+ else
+ {
+ if (atoi (szRest) == 0)
+ {
+ DisplayMessage(IDR_DIVIDE_BY_ZERO);
+ strcpy (buffer, "0");
+ }
+ else
+ {
+ sprintf (buffer, "%d",(chOp == '/')? (atoi (buffer) / atoi (szRest))
+ : (atoi (buffer) % atoi (szRest)));
+ }
+ }
+ }
+ else
+ {
+ strcpy (szRest, buffer);
+ *buffer = 0;
+
+ while (*lpTemp)
+ {
+ if (inquotes)
+ {
+ if (*lpTemp == '\\')
+ TranslateSpecialChar (&lpTemp, &buffer);
+ else if (*lpTemp == '\"')
+ {
+ inquotes = !inquotes;
+ lpTemp++;
+ if (!GetNextString (&lpTemp, &fEnd))
+ break;
+ }
+ else if (*lpTemp == '%')
+ {
+ lpTemp++;
+ DoVarTranslate (&lpTemp, &buffer, MAXLEN-(buffer-lpBuffer), TRUE);
+ }
+ else
+ {
+ *buffer = *lpTemp;
+ if (IsDBCSLeadByte(*buffer))
+ {
+ buffer++;
+ lpTemp++;
+ *buffer = *lpTemp;
+ }
+ buffer++;
+ lpTemp++;
+ }
+ }
+ else
+ {
+ if (*lpTemp == '\"')
+ {
+ inquotes = !inquotes;
+ lpTemp++;
+ }
+ else
+ {
+ if (!DoVarTranslate (&lpTemp, &buffer, MAXLEN-(buffer-lpBuffer), FALSE) ||
+ !GetNextString (&lpTemp, &fEnd))
+ break;
+ }
+ }
+ }
+ if (!fEnd)
+ {
+ if ( inquotes )
+ DisplayMessage( IDR_NO_END_QUOTE );
+ return(FALSE);
+ }
+ *buffer = 0;
+ }
+
+ return(TRUE);
+}
+
+/*
+ * Replace the variables in the string with their value.
+ * Use this function when the input string is quoted format.
+ * Return TRUE if input buffer is right format, FALSE otherwise.
+ */
+int QuotedStringTranslate (char *buffer)
+{
+ char szTemp[MAXLEN], *lpLeft, *lpRight, *ptr = buffer, *pNext;
+ int inquotes;
+
+ lpLeft = *buffer == '('? buffer : NULL;
+ lpRight = *buffer == ')'? buffer : NULL;
+ inquotes = (*ptr == '"');
+
+ while (*ptr)
+ {
+ pNext = NWAnsiNext (ptr);
+
+ if (*pNext == '"' && *(ptr) != '\\')
+ {
+ pNext++;
+ inquotes = !inquotes;
+ }
+
+ ptr = pNext;
+
+ if (!inquotes)
+ {
+ if (*ptr == '(')
+ lpLeft = ptr;
+ else if (*ptr == ')')
+ {
+ lpRight = ptr;
+
+ *lpRight = 0;
+
+ if (lpLeft == NULL)
+ return(FALSE);
+
+ if (lpRight - lpLeft <= 1) //There should be something in the backets.
+ return(FALSE);
+
+ *lpLeft = 0;
+
+ strncpy (szTemp, lpLeft+1, lpRight-lpLeft);
+
+ if (!SingleStringTranslate (szTemp))
+ return(FALSE);
+
+ if (strlen (buffer) + strlen(szTemp) + strlen (lpRight+1) + 2 >= MAXLEN)
+ return(FALSE);
+
+ *lpLeft = '"';
+ *(lpLeft+1+strlen(szTemp)) = '"';
+ memmove (lpLeft+2+strlen(szTemp), lpRight+1, strlen (lpRight+1)+1);
+ memmove (lpLeft+1, szTemp, strlen(szTemp));
+
+ lpLeft = *buffer == '('? buffer : NULL;
+ lpRight = *buffer == ')'? buffer : NULL;
+ ptr = buffer;
+ inquotes = (*ptr == '"');
+ }
+ }
+ }
+
+ if (lpLeft != NULL || lpRight != NULL)
+ return(FALSE);
+ return(SingleStringTranslate (buffer));
+}
+
+
+void BreakOff(void)
+{
+ fBreakOn = FALSE;
+
+ NTBreakOff();
+}
+
+void BreakOn(void)
+{
+ fBreakOn = TRUE;
+
+ NTBreakOn();
+}
+
+/*
+ * Used by ComspecHandler() and SetHandler()
+ * Set dos environment variable.
+ */
+int SetEnv (char *lpEnvLine)
+{
+ ExportEnv( lpEnvLine );
+ return(TRUE);
+}
diff --git a/private/nw/nwscript/sources b/private/nw/nwscript/sources
new file mode 100644
index 000000000..3425d5c96
--- /dev/null
+++ b/private/nw/nwscript/sources
@@ -0,0 +1,85 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+BLDCRT=1
+
+MAJORCOMP=utils
+MINORCOMP=nwscript
+
+C_DEFINES = -DNT=1 -DUNICODE=1
+MSC_WARNING_LEVEL=/W3 /WX
+
+TARGETNAME=nwscript
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+INCLUDES=inc;..\inc;..\..\inc;..\..\..\inc;$(_NTROOT)\private\inc;
+#GPSIZE=32
+
+SOURCES=capture.c \
+ psdb.c \
+ ntcap.c \
+ helpers.c \
+ script.c \
+ display.c \
+ nwapi1.c \
+ nwapi2.c \
+ nwapi3.c \
+ common.c \
+ strings.c \
+ ntscript.c \
+ dbcs.c \
+ parspath.c \
+ nt.c \
+ ntnw.c \
+ drvstat.c \
+ env.c \
+ break.c \
+ attach.c \
+ ncp.c \
+ drive.c \
+ version.c \
+ date.c \
+ wide.c \
+ unc.c \
+ nds.c \
+ ps40db.c \
+ time.c \
+ maplist.c \
+ lsparse.c \
+ nwscript.rc
+
+
+UMTYPE=console
+UMAPPL=nwscript
+UMLIBS=$(BASEDIR)\Public\Sdk\Lib\*\kernel32.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\user32.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\mpr.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\ntdll.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\nwapi32.lib \
+ $(BASEDIR)\Public\Sdk\Lib\*\nwprovau.lib \
+ obj\*\nwscript.lib
+
+UMRES=obj\*\nwscript.res
+
diff --git a/private/nw/nwscript/strings.c b/private/nw/nwscript/strings.c
new file mode 100644
index 000000000..57fb68fab
--- /dev/null
+++ b/private/nw/nwscript/strings.c
@@ -0,0 +1,132 @@
+
+/*************************************************************************
+*
+* STRINGS.C
+*
+* Various strings
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\STRINGS.C $
+*
+* Rev 1.1 22 Dec 1995 14:26:50 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:08:06 terryt
+* Initial revision.
+*
+* Rev 1.1 25 Aug 1995 16:23:56 terryt
+* Capture support
+*
+* Rev 1.0 15 May 1995 19:11:06 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include "common.h"
+
+/*
+ * These haven't been put into resource files, because they aren't user
+ * messages. Most are control information or variables. To do this
+ * right, all output and string processing would have to be changed to
+ * unicode. This can't be done until NetWare and International are
+ * understood.
+ */
+
+
+char *__GREETING__[3] = {"morning", "afternoon", "evening"};
+char *__AMPM__[2] = {"am", "pm"};
+char *__Day__[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
+char *__Month__[12] = {"January", "Feburary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
+char __DEL__[] ="DELETE";
+char __REM__[] ="REMOVE";
+char __INS__[] ="INSERT";
+char __ROOT__[] ="ROOT";
+char __NEXT__[] ="NEXT";
+
+/*
+ * Capture strings
+ */
+unsigned int CaptureStringsLoaded = FALSE;
+WCHAR __DISABLED__[256];
+WCHAR __ENABLED__[256];
+WCHAR __YES__[256];
+WCHAR __NO__[256];
+WCHAR __SECONDS__[256];
+WCHAR __CONVERT_TO_SPACE__[256];
+WCHAR __NO_CONVERSION__[256];
+WCHAR __NOTIFY_USER__[256];
+WCHAR __NOT_NOTIFY_USER__[256];
+WCHAR __NONE__[256];
+
+char __JOB_DESCRIPTION__[] ="LPT%d Catch";
+
+char __OPT_NO__[] ="No";
+
+char __SHOW__[] ="SHOW";
+
+char __NOTIFY__[] ="NOTIFY";
+char __SHORT_FOR_NOTIFY__[] ="NOTI";
+
+char __NONOTIFY__[] ="NONOTIFY";
+char __SHORT_FOR_NONOTIFY__[]="NNOTI";
+
+char __AUTOENDCAP__[] ="AUTOENDCAP";
+char __SHORT_FOR_AUTOENDCAP__[] ="AU";
+
+char __NOAUTOENDCAP__[] ="NOAUTOENDCAP";
+char __SHORT_FOR_NOAUTOENDCAP__[] ="NA";
+
+char __NOTABS__[] ="NOTABS";
+char __SHORT_FOR_NOTABS__[] ="NT";
+
+char __NOBANNER__[] ="NOBANNER";
+char __SHORT_FOR_NOBANNER__[] ="NB";
+
+char __FORMFEED__[] ="FORMFEED";
+char __SHORT_FOR_FORMFEED__[] ="FF";
+
+char __NOFORMFEED__[] ="NOFORMFEED";
+char __SHORT_FOR_NOFORMFEED__[] ="NFF";
+
+char __KEEP__[] ="KEEP";
+char __SHORT_FOR_KEEP__[] ="K";
+
+char __TIMEOUT__[] ="TIMEOUT";
+char __SHORT_FOR_TIMEOUT__[] ="TI";
+
+char __LOCAL__[] ="LOCAL";
+char __SHORT_FOR_LOCAL__[] ="L";
+
+char __LOCAL_3__[] ="LPT";
+char __LOCAL_2__[] ="LP";
+
+char __JOB__[] ="JOB";
+char __SHORT_FOR_JOB__[] ="J";
+
+char __SERVER__[] ="SERVER";
+char __SHORT_FOR_SERVER__[] ="S";
+
+char __QUEUE__[] ="QUEUE";
+char __SHORT_FOR_QUEUE__[] ="Q";
+
+char __PRINTER__[] ="PRINTER";
+char __SHORT_FOR_PRINTER__[] ="P";
+
+char __CREATE__[] ="CREATE";
+char __SHORT_FOR_CREATE__[] ="CR";
+
+char __FORM__[] ="FORM";
+char __SHORT_FOR_FORM__[] ="F";
+
+char __COPIES__[] ="COPIES";
+char __SHORT_FOR_COPIES__[] ="C";
+
+char __TABS__[] ="TABS";
+char __SHORT_FOR_TABS__[] ="T";
+
+char __NAME__[] ="NAME";
+char __SHORT_FOR_NAME__[] ="NAM";
+
+char __BANNER__[] ="BANNER";
+char __SHORT_FOR_BANNER__[] ="B";
diff --git a/private/nw/nwscript/time.c b/private/nw/nwscript/time.c
new file mode 100644
index 000000000..26639359a
--- /dev/null
+++ b/private/nw/nwscript/time.c
@@ -0,0 +1,184 @@
+/*
+ * TIME.C - Various time subroutines needed by NetWare Login Script
+ *
+ * Copyright (c) 1995 Microsoft Corporation
+ */
+
+#include "common.h"
+
+// Needed to convert netware net date to DOS date
+#define _70_to_80_bias 0x012CEA600L
+#define SECS_IN_DAY (60L*60L*24L)
+#define SEC2S_IN_DAY (30L*60L*24L)
+#define FOURYEARS (3*365+366)
+
+WORD MonTotal[] = { 0, // dummy entry for month 0
+ 0, // days before Jan 1
+ 31, // days before Feb 1
+ 31+28, // days before Mar 1
+ 31+28+31, // days before Apr 1
+ 31+28+31+30, // days before May 1
+ 31+28+31+30+31, // days before Jun 1
+ 31+28+31+30+31+30, // days before Jul 1
+ 31+28+31+30+31+30+31, // days before Aug 1
+ 31+28+31+30+31+30+31+31, // days before Sep 1
+ 31+28+31+30+31+30+31+31+30, // days before Oct 1
+ 31+28+31+30+31+30+31+31+30+31, // days before Nov 1
+ 31+28+31+30+31+30+31+31+30+31+30, // days before Dec 1
+ 31+28+31+30+31+30+31+31+30+31+30+31 // days before end of year
+};
+
+#define YR_MASK 0xFE00
+#define LEAPYR_MASK 0x0600
+#define YR_BITS 7
+#define MON_MASK 0x01E0
+#define MON_BITS 4
+#define DAY_MASK 0x001F
+#define DAY_BITS 5
+
+#define HOUR_MASK 0xF800
+#define HOUR_BITS 5
+#define MIN_MASK 0x07E0
+#define MIN_BITS 6
+#define SEC2_MASK 0x001F
+#define SEC2_BITS 5
+
+static void NetToDosDate( DWORD time, WORD * dosdate, WORD * dostime )
+{
+ DWORD secs, days;
+ WORD r;
+
+ time = (time - _70_to_80_bias) / 2; // # of 2 second periods since 1980
+ secs = time % SEC2S_IN_DAY; // 2 second period into day
+ days = time / SEC2S_IN_DAY; // days since Jan 1 1980
+
+ r = (WORD) ( secs % 30 ); // # of 2 second steps
+ secs /= 30;
+ r |= (secs % 60) << SEC2_BITS; // # of minutes
+ r |= (secs / 60) << SEC2_BITS+MIN_BITS; // # of hours
+ *dostime = r;
+
+ r = (WORD) ( days / FOURYEARS );// (r) = four year period past 1980
+ days %= FOURYEARS; // (days) = days into four year period
+ r *= 4; // (r) = years since 1980 (within 3)
+
+ if (days == 31+28) {
+ //* Special case for FEB 29th
+ r = (r<<(MON_BITS+DAY_BITS)) + (2<<DAY_BITS) + 29;
+ } else {
+ if (days > 31+28)
+ --days; // compensate for leap year
+ while (days >= 365) {
+ ++r;
+ days -= 365;
+ }
+
+ for (secs = 1; days >= MonTotal[secs+1] ; ++secs)
+ ;
+ days -= MonTotal[secs];
+ r <<= MON_BITS;
+ r += (WORD)secs;
+ r <<= DAY_BITS;
+ r += (WORD)days+1;
+ }
+ *dosdate = r;
+}
+
+
+#define TIMEDATE_SIZE 64
+
+void nwShowLastLoginTime(VOID)
+{
+ LONG lTime = 0L;
+ SYSTEMTIME st;
+ FILETIME ft;
+ TIME_ZONE_INFORMATION tz;
+ WCHAR szTimeBuf[TIMEDATE_SIZE];
+ WCHAR szDateBuf[TIMEDATE_SIZE];
+ int ret;
+ WORD dostime, dosdate;
+ DWORD tzStat;
+
+ if ( ret = NDSGetUserProperty ("Last Login Time", (PBYTE)&lTime,
+ 4, NULL, NULL) )
+ {
+ #ifdef DEBUG
+ OutputDebugString("NWLSPROC: error getting LOGIN TIME\n\r");
+ #endif
+ return;
+ }
+
+ // From NetWare we get seconds from 1970, need to go through
+ // several conversions to get system time for NLS
+
+ // First deduct bias from UTC time to correct for local time
+ tzStat = GetTimeZoneInformation(&tz);
+ if ( tzStat != (DWORD)-1 ) {
+ if (tzStat == TIME_ZONE_ID_STANDARD)
+ tz.Bias += tz.StandardBias;
+ else if (tzStat == TIME_ZONE_ID_DAYLIGHT)
+ tz.Bias += tz.DaylightBias;
+ lTime -= tz.Bias*60;
+ }
+#ifdef DEBUG
+ else {
+ OutputDebugString("NWLSPROC: GetTimeZoneInformation failed\n\r");
+ }
+#endif // DEBUG
+
+ NetToDosDate( lTime, &dosdate, &dostime );
+ DosDateTimeToFileTime ( dosdate, dostime, &ft );
+ FileTimeToSystemTime ( &ft, &st );
+
+#ifdef notdef
+ // I don't understand this comment, this code doesn't seem to be
+ // needed for NT. - terry
+ //
+ // This code will work on NT, but not on Win95.
+ // Convert the resulting system (UTC) time to local time
+ if ( GetTimeZoneInformation(&tz) != (DWORD)-1 ) {
+ SYSTEMTIME utcTime = st;
+ SystemTimeToTzSpecificLocalTime ( &tz, &utcTime, &st );
+ }
+#ifdef DEBUG
+ else {
+ OutputDebugString("NWLSPROC: GetTimeZoneInformation failed\n\r");
+ }
+#endif // DEBUG
+#endif
+
+ wcscpy(szTimeBuf, L"");
+ ret = GetTimeFormat ( GetSystemDefaultLCID(),
+ TIME_FORCE24HOURFORMAT|TIME_NOTIMEMARKER,
+ &st,
+ NULL,
+ szTimeBuf,
+ TIMEDATE_SIZE );
+#ifdef DEBUG
+ if ( !ret ) {
+ char buf[80];
+ wsprintf(buf,"NWLSPROC: GetTimeFormatA failure: %d sec:%ld\n\r",
+ GetLastError(), lTime );
+ OutputDebugString(buf);
+ }
+#endif
+ ret = GetDateFormat(LOCALE_USER_DEFAULT,
+ DATE_LONGDATE,
+ &st,
+ NULL,
+ szDateBuf,
+ TIMEDATE_SIZE );
+#ifdef DEBUG
+ if ( !ret ) {
+ char buf[80];
+ wsprintf(buf,"NWLSPROC: GetDateFormatA failure: %d sec:%ld\n\r",
+ GetLastError(), lTime );
+ OutputDebugString(buf);
+ }
+#endif
+
+ DisplayMessage( IDR_LASTLOGIN, szDateBuf, szTimeBuf );
+}
+
+
+
diff --git a/private/nw/nwscript/unc.c b/private/nw/nwscript/unc.c
new file mode 100644
index 000000000..8f99320b9
--- /dev/null
+++ b/private/nw/nwscript/unc.c
@@ -0,0 +1,142 @@
+/*************************************************************************
+*
+* UNC.C
+*
+* NetWare format to UNC format
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\UNC.C $
+*
+* Rev 1.4 10 Apr 1996 14:24:00 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.4 12 Mar 1996 19:56:18 terryt
+* Relative NDS names and merge
+*
+* Rev 1.3 04 Jan 1996 18:57:26 terryt
+* Bug fixes reported by MS
+*
+* Rev 1.2 22 Dec 1995 14:27:04 terryt
+* Add Microsoft headers
+*
+* Rev 1.1 22 Dec 1995 11:09:18 terryt
+* Fixes
+*
+* Rev 1.0 15 Nov 1995 18:08:14 terryt
+* Initial revision.
+*
+* Rev 1.1 23 May 1995 19:37:24 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:11:10 terryt
+* Initial revision.
+*
+*************************************************************************/
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "inc/common.h"
+
+/********************************************************************
+
+ NTNWtoUNCFormat
+
+Routine Description:
+
+ Given a connection handle and a path, change it to UNC format
+ if it's in NetWare format. I.E.
+
+ SYS:\usr\terryt ==> \\HELIUM\SYS\usr\terryt
+
+ Don't do the conversion if it's not in NetWare format.
+
+Arguments:
+
+ ConnectionHandle - Connection Handle
+ NetWarePath - Input original path
+
+Return Value:
+ UNC string
+
+ *******************************************************************/
+char *
+NTNWtoUNCFormat( char * NetWarePath )
+{
+ static char UNCPath[1024];
+ unsigned int Result;
+ char ServerName[48];
+ char * p;
+ char * q;
+
+ /*
+ * If it's UNC already, leave it alone
+ */
+ if ( ( NetWarePath[0] == '\\' ) && ( NetWarePath[1] == '\\' ) )
+ return NetWarePath;
+ if ( ( NetWarePath[0] == '/' ) && ( NetWarePath[1] == '/' ) )
+ return NetWarePath;
+
+ /*
+ * if it's drive:dir, leave it alone
+ */
+ if ( NetWarePath[0] && ( NetWarePath[1] == ':' ) )
+ return NetWarePath;
+
+ /*
+ * if it's not volume:dir, leave it alone
+ */
+ p = strchr( NetWarePath, ':' );
+ if ( !p )
+ return NetWarePath;
+
+ /*
+ * if slashes before :, it must be a file server
+ */
+ q = strchr( NetWarePath, '\\' );
+ if ( q && ( q < p ) )
+ {
+ strcpy( UNCPath, "\\\\" );
+ *p = '\0';
+ strcat( UNCPath, NetWarePath );
+ if (( *(p + 1) != '\\' ) && ( *(p + 1) != '/' ) )
+ strcat( UNCPath, "\\" );
+ strcat( UNCPath, p + 1 );
+ *p = ':';
+ return UNCPath;
+ }
+
+ q = strchr( NetWarePath, '/' );
+ if ( q && ( q < p ) )
+ {
+ strcpy( UNCPath, "\\\\" );
+ *q = '\\';
+ *p = '\0';
+ strcat( UNCPath, NetWarePath );
+ if (( *(p + 1) != '\\' ) && ( *(p + 1) != '/' ) )
+ strcat( UNCPath, "\\" );
+ strcat( UNCPath, p + 1 );
+ *q = '/';
+ *p = ':';
+ return UNCPath;
+ }
+
+ strcpy( UNCPath, "\\\\" );
+ strcat( UNCPath, PREFERRED_SERVER );
+ strcat( UNCPath, "\\" );
+ *p = '\0';
+ strcat( UNCPath, NetWarePath );
+ if (( *(p + 1) != '\\' ) && ( *(p + 1) != '/' ) )
+ strcat( UNCPath, "\\" );
+ strcat( UNCPath, p + 1 );
+ *p = ':';
+
+ return UNCPath;
+}
diff --git a/private/nw/nwscript/version.c b/private/nw/nwscript/version.c
new file mode 100644
index 000000000..b4ce000d6
--- /dev/null
+++ b/private/nw/nwscript/version.c
@@ -0,0 +1,68 @@
+/*************************************************************************
+*
+* VERSION.C
+*
+* Shell version information
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\VERSION.C $
+*
+* Rev 1.2 10 Apr 1996 14:24:08 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:56:28 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:27:10 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:08:18 terryt
+* Initial revision.
+*
+* Rev 1.1 26 Jul 1995 14:17:24 terryt
+* Clean up comments
+*
+* Rev 1.0 15 May 1995 19:11:12 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "nwscript.h"
+
+
+/*
+ * MSDOS is not neccessarily the best thing to put out,
+ * maybe Windows_NT, NT or NTDOS. The OS_VERSION is also a problem.
+ * The script variables don't neccessarily have to match the DOS variables.
+ *
+ * The shell version numbers may change with 4.X support.
+ */
+
+#define CLIENT_ID_STRING "MSDOS\0V5.00\0IBM_PC\0IBM"
+#define CLIENT_SHELL_MAJOR 0x03
+#define CLIENT_SHELL_MINOR 0x1a
+#define CLIENT_SHELL_NUMBER 0x00
+
+
+void
+NTGetVersionOfShell( char * buffer,
+ unsigned char * shellmajor,
+ unsigned char * shellminor,
+ unsigned char * shellnum )
+{
+ *shellmajor = CLIENT_SHELL_MAJOR;
+ *shellminor = CLIENT_SHELL_MINOR;
+ *shellnum = CLIENT_SHELL_NUMBER;
+ memcpy( buffer, CLIENT_ID_STRING, 40 );
+}
diff --git a/private/nw/nwscript/wide.c b/private/nw/nwscript/wide.c
new file mode 100644
index 000000000..09578c7bd
--- /dev/null
+++ b/private/nw/nwscript/wide.c
@@ -0,0 +1,149 @@
+/*************************************************************************
+*
+* WIDE.C
+*
+* Wide character translation routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+* $Log: N:\NT\PRIVATE\NW4\NWSCRIPT\VCS\WIDE.C $
+*
+* Rev 1.2 10 Apr 1996 14:24:14 terryt
+* Hotfix for 21181hq
+*
+* Rev 1.2 12 Mar 1996 19:56:36 terryt
+* Relative NDS names and merge
+*
+* Rev 1.1 22 Dec 1995 14:27:18 terryt
+* Add Microsoft headers
+*
+* Rev 1.0 15 Nov 1995 18:08:20 terryt
+* Initial revision.
+*
+* Rev 1.1 23 May 1995 19:37:32 terryt
+* Spruce up source
+*
+* Rev 1.0 15 May 1995 19:11:14 terryt
+* Initial revision.
+*
+*************************************************************************/
+
+#include <stdio.h>
+#include <direct.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "nwscript.h"
+
+
+/********************************************************************
+
+ szToWide
+
+Routine Description:
+
+ Given a single byte character string, convert to wide
+
+Arguments:
+
+ lpszW - Wide character string returned
+ lpszC - Single character string input
+ nSize - length of Wide character buffer
+
+Return Value:
+ 0 = success
+ else NT error
+
+ *******************************************************************/
+DWORD
+szToWide(
+ LPWSTR lpszW,
+ LPCSTR lpszC,
+ INT nSize
+ )
+{
+ if (!MultiByteToWideChar(CP_OEMCP,
+ MB_PRECOMPOSED,
+ lpszC,
+ -1,
+ lpszW,
+ nSize))
+ {
+ return (GetLastError()) ;
+ }
+
+ return NO_ERROR ;
+}
+
+/********************************************************************
+
+ WideTosz
+
+Routine Description:
+
+ Given a wide character string, convert to single
+
+Arguments:
+
+ lpszC - Single character string returned
+ lpszW - Wide character string input
+ nSize - length of single character buffer
+
+Return Value:
+ 0 = success
+ else NT error
+
+ *******************************************************************/
+DWORD
+WideTosz(
+ LPSTR lpszC,
+ LPWSTR lpszW,
+ INT nSize
+ )
+{
+ if (!WideCharToMultiByte(CP_OEMCP,
+ 0,
+ (LPCWSTR) lpszW,
+ -1,
+ lpszC,
+ nSize,
+ NULL,
+ NULL))
+ {
+ return (GetLastError()) ;
+ }
+
+ return NO_ERROR ;
+}
+
+/********************************************************************
+
+ ConvertUnicodeToAscii
+
+Routine Description:
+
+ Given a wide character string, convert to single
+
+Arguments:
+
+ Buffer - buffer to be converted
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+ConvertUnicodeToAscii( PVOID Buffer )
+{
+ LPCWSTR lpszW = Buffer;
+ BYTE Destination[1024];
+
+ WideTosz( (LPSTR)Destination, (LPWSTR)Buffer, 1024 );
+
+ strcpy( Buffer, Destination );
+}