380 lines
9.2 KiB
C
380 lines
9.2 KiB
C
/********************************************************************/
|
|
/** Microsoft LAN Manager **/
|
|
/** Copyright(c) Microsoft Corp., 1987-1990 **/
|
|
/********************************************************************/
|
|
|
|
/*
|
|
* MSNET - a command processor for MSNET 3.0.
|
|
* The command grammar is specified in msnet.x
|
|
*
|
|
* History
|
|
*
|
|
* ??/??/??, ??????, initial code
|
|
* 10/31/88, erichn, uses OS2.H instead of DOSCALLS
|
|
* 05/02/89, erichn, NLS conversion
|
|
* 06/08/89, erichn, canonicalization sweep, no LONGer u-cases input
|
|
* 02/15/91, danhi, convert to be 16/32 portable
|
|
* 10/16/91, JohnRo, added DEFAULT_SERVER support.
|
|
*/
|
|
|
|
/* #define INCL_NOCOMMON */
|
|
#include <os2.h>
|
|
#include <lmcons.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
#include <apperr.h>
|
|
#include "netcmds.h"
|
|
#include "nettext.h"
|
|
#include "msystem.h"
|
|
#include "locale.h"
|
|
|
|
#define _SHELL32_
|
|
#include <shellapi.h>
|
|
|
|
|
|
static VOID init(VOID);
|
|
VOID call_net1(VOID) ;
|
|
|
|
TCHAR * ArgList[LIST_SIZE] = {0};
|
|
SHORT ArgPos[LIST_SIZE] = {0};
|
|
TCHAR * SwitchList[LIST_SIZE] = {0};
|
|
SHORT SwitchPos[LIST_SIZE] = {0};
|
|
|
|
/* Insertion strings for InfoMessage() */
|
|
TCHAR FAR * IStrings[10] = {0};
|
|
TCHAR FAR * StarStrings[10] = {TEXT("***"),
|
|
TEXT("***"),
|
|
TEXT("***"),
|
|
TEXT("***"),
|
|
TEXT("***"),
|
|
TEXT("***"),
|
|
TEXT("***"),
|
|
TEXT("***"),
|
|
TEXT("***")};
|
|
|
|
/* 1 is /Yes, 2 is /No */
|
|
SHORT YorN_Switch = 0;
|
|
TCHAR ** MyArgv; /* argv */
|
|
|
|
UINT SavedArgc = 0 ;
|
|
CHAR ** SavedArgv = NULL ;
|
|
|
|
/* Buffers for APIs to use */
|
|
TCHAR Buffer[LITTLE_BUF_SIZE]; /* For GetInfo's, etc.*/
|
|
TCHAR BigBuffer[BIG_BUF_SIZE]; /* For Enum's */
|
|
TCHAR FAR * BigBuf = BigBuffer;
|
|
|
|
//
|
|
// Globals for standard console handles
|
|
//
|
|
|
|
HANDLE g_hStdOut;
|
|
HANDLE g_hStdErr;
|
|
|
|
|
|
/***
|
|
* MAIN - Seperate the command line into switches and arguments.
|
|
* Then call the parser, which will dispatch the command and
|
|
* report on error conditions. Allocate the BigBuf.
|
|
*/
|
|
|
|
VOID os2cmd(VOID);
|
|
CPINFO CurrentCPInfo;
|
|
|
|
VOID __cdecl main(int argc, CHAR **argv)
|
|
{
|
|
SHORT sindex, aindex;
|
|
SHORT pos=0;
|
|
DWORD cp;
|
|
CHAR achCodePage[12] = ".OCP"; // '.' + UINT in decimal + '\0'
|
|
|
|
SavedArgc = argc ;
|
|
SavedArgv = argv ;
|
|
|
|
|
|
/*
|
|
Added for bilingual message support. This is needed for FormatMessage
|
|
to work correctly. (Called from DosGetMessage).
|
|
Get current CodePage Info. We need this to decide whether
|
|
or not to use half-width characters.
|
|
*/
|
|
|
|
cp = GetConsoleOutputCP();
|
|
|
|
GetCPInfo(cp, &CurrentCPInfo);
|
|
|
|
switch ( cp )
|
|
{
|
|
case 932:
|
|
case 936:
|
|
case 949:
|
|
case 950:
|
|
SetThreadLocale(
|
|
MAKELCID(
|
|
MAKELANGID(
|
|
PRIMARYLANGID(GetSystemDefaultLangID()),
|
|
SUBLANG_ENGLISH_US ),
|
|
SORT_DEFAULT
|
|
)
|
|
);
|
|
break;
|
|
|
|
default:
|
|
SetThreadLocale(
|
|
MAKELCID(
|
|
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
|
|
SORT_DEFAULT
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
|
|
if (cp)
|
|
{
|
|
sprintf(achCodePage, ".%u", cp);
|
|
}
|
|
|
|
setlocale(LC_ALL, achCodePage);
|
|
|
|
g_hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
if (g_hStdOut == INVALID_HANDLE_VALUE)
|
|
{
|
|
ErrorExit(GetLastError());
|
|
}
|
|
|
|
g_hStdErr = GetStdHandle(STD_ERROR_HANDLE);
|
|
|
|
if (g_hStdErr == INVALID_HANDLE_VALUE)
|
|
{
|
|
ErrorExit(GetLastError());
|
|
}
|
|
|
|
MyArgv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
|
if (MyArgv == NULL)
|
|
{
|
|
ErrorExit(ERROR_NOT_ENOUGH_MEMORY) ;
|
|
}
|
|
|
|
/* seperate switches and arguments */
|
|
++MyArgv;
|
|
for (sindex = 0, aindex = 0; --argc; ++MyArgv, ++pos)
|
|
{
|
|
if (**MyArgv == SLASH)
|
|
{
|
|
SHORT arglen;
|
|
SHORT arg_is_special = 0;
|
|
|
|
arglen = (SHORT) _tcslen(*MyArgv);
|
|
|
|
if (arglen > 1)
|
|
{
|
|
if ( _tcsnicmp(swtxt_SW_YES, (*MyArgv), arglen) == 0 )
|
|
{
|
|
if (YorN_Switch == NO)
|
|
ErrorExit(APE_ConflictingSwitches);
|
|
arg_is_special = 1;
|
|
YorN_Switch = YES;
|
|
}
|
|
else if ( _tcsnicmp(swtxt_SW_NO, (*MyArgv), arglen) == 0 )
|
|
{
|
|
if (YorN_Switch == YES)
|
|
ErrorExit(APE_ConflictingSwitches);
|
|
arg_is_special = 1;
|
|
YorN_Switch = NO;
|
|
}
|
|
}
|
|
|
|
if ( ! arg_is_special )
|
|
{
|
|
if (sindex >= LIST_SIZE)
|
|
ErrorExit(APE_NumArgs) ;
|
|
SwitchList[sindex] = *MyArgv;
|
|
SwitchPos[sindex] = pos;
|
|
sindex++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (aindex >= LIST_SIZE)
|
|
ErrorExit(APE_NumArgs) ;
|
|
ArgList[aindex] = *MyArgv;
|
|
ArgPos[aindex] = pos;
|
|
aindex++;
|
|
}
|
|
}
|
|
|
|
// register as locations to zero out on exit
|
|
AddToMemClearList(BigBuffer, sizeof(BigBuffer), FALSE) ;
|
|
AddToMemClearList(Buffer, sizeof(Buffer),FALSE) ;
|
|
|
|
init();
|
|
|
|
os2cmd();
|
|
|
|
NetcmdExit(0);
|
|
}
|
|
|
|
|
|
static VOID NEAR init(VOID)
|
|
{
|
|
_setmode(_fileno(stdin), O_TEXT);
|
|
}
|
|
|
|
/***
|
|
* M y E x i t
|
|
*
|
|
* Wrapper around C runtime that cleans up memory for security reasons.
|
|
*/
|
|
|
|
VOID DOSNEAR FASTCALL
|
|
MyExit(int Status)
|
|
{
|
|
ClearMemory() ;
|
|
exit(Status);
|
|
}
|
|
|
|
typedef struct _MEMOMY_ELEMENT {
|
|
LPBYTE lpLocation ;
|
|
struct _MEMORY_ELEMENT *lpNext ;
|
|
UINT nSize ;
|
|
BOOL fDelete ;
|
|
} MEMORY_ELEMENT, *LPMEMORY_ELEMENT ;
|
|
|
|
LPMEMORY_ELEMENT lpToDeleteList = NULL ;
|
|
|
|
/***
|
|
* AddToMemClearList
|
|
*
|
|
* add an entry to list of things to clear
|
|
*/
|
|
VOID
|
|
AddToMemClearList(
|
|
VOID *lpBuffer,
|
|
UINT nSize,
|
|
BOOL fDelete
|
|
)
|
|
{
|
|
LPMEMORY_ELEMENT lpNew, lpTmp ;
|
|
DWORD err ;
|
|
|
|
if (err = AllocMem(sizeof(MEMORY_ELEMENT),(LPBYTE *) &lpNew))
|
|
{
|
|
ErrorExit(err);
|
|
}
|
|
|
|
lpNew->lpLocation = (LPBYTE) lpBuffer ;
|
|
lpNew->nSize = nSize ;
|
|
lpNew->fDelete = fDelete ;
|
|
lpNew->lpNext = NULL ;
|
|
|
|
if (!lpToDeleteList)
|
|
{
|
|
lpToDeleteList = lpNew ;
|
|
}
|
|
else
|
|
{
|
|
lpTmp = lpToDeleteList ;
|
|
while (lpTmp->lpNext)
|
|
lpTmp = (LPMEMORY_ELEMENT) lpTmp->lpNext ;
|
|
lpTmp->lpNext = (struct _MEMORY_ELEMENT *) lpNew ;
|
|
}
|
|
}
|
|
|
|
/***
|
|
* ClearMemory()
|
|
*
|
|
* go thru list of things to clear, and clear them.
|
|
*/
|
|
VOID ClearMemory(VOID)
|
|
{
|
|
|
|
LPMEMORY_ELEMENT lpList, lpTmp ;
|
|
UINT index ;
|
|
|
|
/*
|
|
* Go thru memory registered to be cleaned up.
|
|
*/
|
|
lpList = lpToDeleteList ;
|
|
while (lpList)
|
|
{
|
|
memset(lpList->lpLocation, 0, lpList->nSize) ;
|
|
lpTmp = (LPMEMORY_ELEMENT) lpList->lpNext ;
|
|
if (lpList->fDelete)
|
|
{
|
|
FreeMem(lpList->lpLocation);
|
|
}
|
|
|
|
FreeMem( (LPBYTE) lpList);
|
|
lpList = lpTmp ;
|
|
}
|
|
lpToDeleteList = NULL ;
|
|
|
|
/*
|
|
* cleanup our copy of the args
|
|
*/
|
|
index = 0;
|
|
while (ArgList[index])
|
|
{
|
|
ClearStringW(ArgList[index]) ;
|
|
index++ ;
|
|
}
|
|
|
|
/*
|
|
* cleanup original argv
|
|
*/
|
|
for ( index = 1 ; index < SavedArgc ; index++ )
|
|
{
|
|
ClearStringA(SavedArgv[index]) ;
|
|
}
|
|
ClearStringW(GetCommandLine());
|
|
}
|
|
|
|
VOID call_net1(VOID)
|
|
{
|
|
STARTUPINFO startupinfo ;
|
|
PROCESS_INFORMATION processinfo;
|
|
LPWSTR cmdline, newcmdline, firstarg;
|
|
DWORD err ;
|
|
int net1exitcode = 0;
|
|
|
|
|
|
memset(&startupinfo, 0, sizeof(startupinfo)) ;
|
|
startupinfo.cb = sizeof(startupinfo);
|
|
cmdline = GetCommandLineW() ;
|
|
firstarg = _tcschr(cmdline, TEXT(' ')) ;
|
|
|
|
if (err = AllocMem((_tcslen(cmdline)+1) * sizeof(TCHAR)
|
|
+ sizeof(TEXT("net1")),
|
|
(LPBYTE *)&newcmdline))
|
|
{
|
|
ErrorExit(err) ;
|
|
}
|
|
|
|
_tcscpy(newcmdline, TEXT("net1")) ;
|
|
if (firstarg)
|
|
_tcscat(newcmdline, firstarg) ;
|
|
|
|
if (!CreateProcess(NULL,
|
|
newcmdline,
|
|
NULL,
|
|
NULL,
|
|
TRUE,
|
|
NORMAL_PRIORITY_CLASS,
|
|
NULL,
|
|
NULL,
|
|
&startupinfo,
|
|
&processinfo))
|
|
{
|
|
ErrorExit(GetLastError());
|
|
}
|
|
|
|
CloseHandle(processinfo.hThread) ;
|
|
WaitForSingleObject(processinfo.hProcess, INFINITE) ;
|
|
GetExitCodeProcess(processinfo.hProcess, &net1exitcode) ;
|
|
CloseHandle(processinfo.hProcess) ;
|
|
MyExit(net1exitcode) ;
|
|
}
|