mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5295 lines
153 KiB
5295 lines
153 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dllnet16.c
|
|
|
|
Abstract:
|
|
|
|
This module implements 32 bit equivalents of OS/2 V1.21
|
|
LANMAN API Calls.
|
|
The APIs are called from 16->32 thunks (i386\doscalls.asm).
|
|
|
|
Author:
|
|
|
|
Beni Lavi (BeniL) 15-Jan-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#define INCL_OS2V20_ERRORS
|
|
#define INCL_OS2V20_ERRORMSG
|
|
#define INCL_OS2V20_MEMORY
|
|
#define INCL_OS2V20_TASKING
|
|
#define UNICODE 1
|
|
#include <stdlib.h>
|
|
#include "os2dll.h"
|
|
#include "os2dll16.h"
|
|
#define WIN32_ONLY
|
|
#include "netrqust.h"
|
|
#include "os2net16.h"
|
|
#include <nb30.h>
|
|
#include "nb30p.h"
|
|
#define APINAMES
|
|
#include <apinums.h> // API_W numbers
|
|
// #include <rxp.h> // RxpTransactSmb
|
|
|
|
#if DBG
|
|
extern USHORT Os2DebugTID;
|
|
#endif
|
|
|
|
//
|
|
// some constants
|
|
//
|
|
|
|
//
|
|
// LanMan API related constants
|
|
//
|
|
|
|
#define LARGE_BUFFER_SIZE 16384 // used for copying large user buffer to internal buffer
|
|
#define SMALL_BUFFER_SIZE 4096 // used for copying small user buffer to internal buffer
|
|
#define PREFMAXLEN 8192 // parameter used to control internal LanMan buffer size
|
|
|
|
//
|
|
// Netbios API related constants
|
|
//
|
|
|
|
#define USERS_STACK_SIZE 4096 // stack size for user's Netbios 3.0 post routine
|
|
#define NETBIOS2_SEMANTICS_SIGNATURE 0xF91E0873 // used as a special flag for Net16bios
|
|
|
|
/*
|
|
We need a hard coded maximum parallel asynch ncbs limit for netbios 2
|
|
requests. The reason is a problem with the NT netbios driver -- Once
|
|
you fill up some maximal number (observed - 0xac) of ncbs, and run out
|
|
of memory, it is no longer possible to send even a cancel request for
|
|
those ncbs. On Os/2 it is still possible to cancel the pending requests.
|
|
Some programs try to test the driver's limits by issuing a lot of ncbs,
|
|
and when they get an error, they cancel them all. This will fail due to
|
|
the above reason. Limiting artificially to a smaller number will allow
|
|
the cancel ncbs to go through. Note that if more than one process fills
|
|
up the driver at the same time, this per-process limit will not do any good.
|
|
Let's hope this situation is unlikely.
|
|
*/
|
|
#define MAX_ASYNCH_NCBS 0x80L
|
|
|
|
|
|
//
|
|
// macro to probe string arguments passed to APIs
|
|
//
|
|
#define PROBE_STRING(s) ((VOID) ((s) == NULL ? 0 : strlen(s)))
|
|
|
|
|
|
//
|
|
// Extended NCB to be passed to Win32 Netbios API
|
|
// It contains parameters that are needed by the ASYNCH processing
|
|
//
|
|
typedef struct _NCBX {
|
|
NCB n;
|
|
PNCB original_pncb; // Original Os/2 program NCB
|
|
ULONG original_ncb_post; // Os/2 program 16 bit far pointer post address
|
|
// or a semaphore handle to clear
|
|
HANDLE Net16BiosHasCompleted; // an event used to sync the post routine with Net16bios
|
|
} NCBX, *PNCBX;
|
|
|
|
|
|
//
|
|
// some important service names for LanMan related APIs
|
|
//
|
|
static CHAR N_LanmanWorkstati[] = "LanmanWorkstati";
|
|
static CHAR N_LanmanWorkstation[] = "LanmanWorkstation";
|
|
static CHAR N_LanmanServer[] = "LanmanServer";
|
|
static CHAR N_Workstation[] = "Workstation";
|
|
static CHAR N_Server[] = "Server";
|
|
|
|
|
|
//
|
|
// netbios related global variables
|
|
//
|
|
|
|
BOOLEAN Od2Netbios2Initialized = FALSE; // netbios 2 initialization flag
|
|
RTL_CRITICAL_SECTION Od2NbSyncCrit; // This CS is used to protect several data structures
|
|
// It's initialized/cleanedup from dllnb.c
|
|
|
|
//
|
|
// Od2LanaEnum holds the permanent enumeration of lana numbers (received from server)
|
|
// Od2LanaState is a per-lana flag that has the following value:
|
|
// bit 0 -- 1 if the lana is open/0 if the lana is closed
|
|
// bit 1 -- 1 if the lana has been opened by this process before/0 if not (and therefore may need a reset thru the server)
|
|
//
|
|
static LANA_ENUM Od2LanaEnum;
|
|
static UCHAR Od2LanaState[MAX_LANA];
|
|
HANDLE Od2NbDev; // handle to NT netbios driver
|
|
LONG Od2MaxAsynchNcbs; // a counter for implementing max asynch ncbs limit
|
|
PVOID Od2Nb2Heap; // special heap for netbios 2 requests
|
|
|
|
//
|
|
// a flag indicating if we've already attached the win32 netbios worker thread to our subsystem
|
|
//
|
|
static BOOLEAN Od2WorkerThreadIsAttached = FALSE;
|
|
static SEL Od2UserStackSel, // selector for netbios post routine user's stack
|
|
Od2UserStackAlias; // code alias for Od2UserStackSel
|
|
|
|
|
|
// imports
|
|
|
|
APIRET
|
|
DosCreateCSAlias(
|
|
IN SEL selDS,
|
|
OUT PSEL pselCS
|
|
);
|
|
|
|
APIRET
|
|
GetSystemDirectoryW(
|
|
LPWSTR lpBuffer,
|
|
ULONG uSize
|
|
);
|
|
|
|
VOID
|
|
Od2JumpTo16NetBiosPostDispatcher(
|
|
IN PVOID pUsersPostRoutine, // CS:IP format
|
|
IN PVOID UserStackFlat, // Flat pointer to user stack
|
|
IN USHORT UserStackSize, // User stack size
|
|
IN SEL UserStackSel, // Data selector to user stack
|
|
IN SEL UserStackAlias, // Code selector to user stack
|
|
IN PVOID pNcb, // 16 bit SEG:OFF ptr to NCB
|
|
IN UCHAR NcbRetCode // return code from NCB
|
|
);
|
|
|
|
APIRET
|
|
Od2AttachWinThreadToOs2(VOID);
|
|
|
|
UCHAR
|
|
Od2Netbios(
|
|
IN PNCB pncb,
|
|
IN HANDLE hDev,
|
|
OUT PBOOLEAN WillPost OPTIONAL
|
|
);
|
|
|
|
//
|
|
// the following 2 are imported from win32
|
|
//
|
|
|
|
LONG
|
|
InterlockedIncrement(
|
|
PLONG lpAddend
|
|
);
|
|
|
|
LONG
|
|
InterlockedDecrement(
|
|
PLONG lpAddend
|
|
);
|
|
|
|
|
|
//
|
|
// the following is from net\inc\rxp.h
|
|
//
|
|
APIRET
|
|
RxpTransactSmb(
|
|
IN LPTSTR UncServerName,
|
|
IN LPTSTR TransportName,
|
|
IN LPVOID SendParmPtr,
|
|
IN DWORD SendParmSize,
|
|
IN LPVOID SendDataPtr OPTIONAL,
|
|
IN DWORD SendDataSize,
|
|
OUT LPVOID RetParmPtr OPTIONAL,
|
|
IN DWORD RetParmSize,
|
|
OUT LPVOID RetDataPtr OPTIONAL,
|
|
IN OUT LPDWORD RetDataSize,
|
|
IN BOOL NoPermissionRequired
|
|
);
|
|
|
|
APIRET
|
|
VrRemoteApi(
|
|
IN DWORD ApiNumber,
|
|
IN LPSTR ServerNamePointer,
|
|
IN LPSTR ParameterDescriptor,
|
|
IN LPSTR DataDescriptor,
|
|
IN LPSTR AuxDescriptor,
|
|
IN BOOL NullSessionFlag
|
|
);
|
|
|
|
APIRET
|
|
VrEncryptSES(
|
|
IN LPSTR ServerNamePointer,
|
|
IN LPSTR passwordPointer, // Input password (Not encripted)
|
|
IN LPSTR encryptedLmOwfPassword // output password (encripted)
|
|
);
|
|
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//Following are a number of Unicode conversion routines used in the LanMan APIs
|
|
//
|
|
//*****************************************************************************
|
|
|
|
|
|
//
|
|
// Get the length of a Unicode string (Adjusted)
|
|
//
|
|
ULONG
|
|
UWstrlen(LPWSTR s)
|
|
{
|
|
ULONG i = 0;
|
|
|
|
if (s == NULL) {
|
|
return(0);
|
|
}
|
|
|
|
while (*s++ != UNICODE_NULL) {
|
|
i++;
|
|
}
|
|
return(i);
|
|
}
|
|
|
|
|
|
ULONG
|
|
UTstrlen(LPTSTR s)
|
|
{
|
|
ULONG i = 0;
|
|
|
|
if (s == NULL) {
|
|
return(0);
|
|
}
|
|
|
|
while (*s++ != 0) {
|
|
i++;
|
|
}
|
|
return(i);
|
|
}
|
|
|
|
|
|
//
|
|
// Copy a Unicode string to Ansi string
|
|
//
|
|
PCHAR
|
|
UW2ANSIstrcpy(PCHAR d, LPWSTR s)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
*d = '\0';
|
|
return(d);
|
|
}
|
|
|
|
RtlInitUnicodeString(&str_u, (PWSTR) s);
|
|
|
|
str_a.Buffer = d;
|
|
str_a.MaximumLength = 0xffff;
|
|
|
|
Od2UnicodeStringToMBString(&str_a, &str_u, FALSE);
|
|
|
|
d[str_a.Length] = '\0';
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
PCHAR
|
|
UT2ANSIstrcpy(PCHAR d, LPTSTR s)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
*d = '\0';
|
|
return(d);
|
|
}
|
|
|
|
RtlInitUnicodeString(&str_u, (PWSTR) s);
|
|
|
|
str_a.Buffer = d;
|
|
str_a.MaximumLength = 0xffff;
|
|
|
|
Od2UnicodeStringToMBString(&str_a, &str_u, FALSE);
|
|
|
|
d[str_a.Length] = '\0';
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
//
|
|
// Copy a Unicode string to Ansi string with a limit on the # of copied chars
|
|
//
|
|
PCHAR
|
|
UW2ANSIstrncpy(PCHAR d, LPWSTR s, ULONG Limit)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
*d = '\0';
|
|
return(d);
|
|
}
|
|
|
|
RtlInitUnicodeString(&str_u, (PWSTR) s);
|
|
|
|
str_a.Buffer = d;
|
|
str_a.MaximumLength = (USHORT) Limit;
|
|
|
|
if (Od2UnicodeStringToMBString(&str_a, &str_u, FALSE) == NO_ERROR) {
|
|
|
|
if ((ULONG) str_a.Length < Limit) {
|
|
d[str_a.Length] = '\0';
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Od2UnicodeStringToMBString(&str_a, &str_u, TRUE) == NO_ERROR) {
|
|
|
|
RtlMoveMemory(d, str_a.Buffer, Limit);
|
|
Od2FreeMBString(&str_a);
|
|
|
|
} else {
|
|
d[0] = '\0';
|
|
}
|
|
}
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
PCHAR
|
|
UT2ANSIstrncpy(PCHAR d, LPTSTR s, ULONG Limit)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
*d = '\0';
|
|
return(d);
|
|
}
|
|
|
|
RtlInitUnicodeString(&str_u, (PWSTR) s);
|
|
|
|
str_a.Buffer = d;
|
|
str_a.MaximumLength = (USHORT) Limit;
|
|
|
|
if (Od2UnicodeStringToMBString(&str_a, &str_u, FALSE) == NO_ERROR) {
|
|
|
|
if ((ULONG) str_a.Length < Limit) {
|
|
d[str_a.Length] = '\0';
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Od2UnicodeStringToMBString(&str_a, &str_u, TRUE) == NO_ERROR) {
|
|
|
|
RtlMoveMemory(d, str_a.Buffer, Limit);
|
|
Od2FreeMBString(&str_a);
|
|
|
|
} else {
|
|
d[0] = '\0';
|
|
}
|
|
}
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
//
|
|
// Copy an ANSI string to Unicode string
|
|
//
|
|
LPWSTR
|
|
ANSI2UWstrcpy(LPWSTR d, PCHAR s)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
*d = UNICODE_NULL;
|
|
return(d);
|
|
}
|
|
|
|
Od2InitMBString(&str_a, (PCSZ) s);
|
|
|
|
str_u.Buffer = (PWSTR) d;
|
|
str_u.MaximumLength = 0xffff;
|
|
|
|
Od2MBStringToUnicodeString(&str_u, &str_a, FALSE);
|
|
|
|
d[str_u.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
LPTSTR
|
|
ANSI2UTstrcpy(LPTSTR d, PCHAR s)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
*d = UNICODE_NULL;
|
|
return(d);
|
|
}
|
|
|
|
Od2InitMBString(&str_a, (PCSZ) s);
|
|
|
|
str_u.Buffer = (PWSTR) d;
|
|
str_u.MaximumLength = 0xffff;
|
|
|
|
Od2MBStringToUnicodeString(&str_u, &str_a, FALSE);
|
|
|
|
d[str_u.Length/sizeof(WCHAR)] = 0;
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
//
|
|
// Copy an Ansi string to a Unicode string with a limit on the # of copied chars
|
|
//
|
|
LPWSTR
|
|
ANSI2UWstrncpy(LPWSTR d, PCHAR s, ULONG Limit)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
*d = UNICODE_NULL;
|
|
return(d);
|
|
}
|
|
|
|
Od2InitMBString(&str_a, s);
|
|
|
|
str_u.Buffer = (PWSTR) d;
|
|
str_u.MaximumLength = (USHORT) (Limit * sizeof(WCHAR));
|
|
|
|
if (Od2MBStringToUnicodeString(&str_u, &str_a, FALSE) == NO_ERROR) {
|
|
|
|
if (str_u.Length < str_u.MaximumLength) {
|
|
d[str_u.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Od2MBStringToUnicodeString(&str_u, &str_a, TRUE) == NO_ERROR) {
|
|
|
|
RtlMoveMemory(d, str_u.Buffer, Limit * sizeof(WCHAR));
|
|
RtlFreeUnicodeString(&str_u);
|
|
|
|
} else {
|
|
d[0] = UNICODE_NULL;
|
|
}
|
|
}
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
LPTSTR
|
|
ANSI2UTstrncpy(LPTSTR d, PCHAR s, ULONG Limit)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
*d = 0;
|
|
return(d);
|
|
}
|
|
|
|
Od2InitMBString(&str_a, s);
|
|
|
|
str_u.Buffer = (PWSTR) d;
|
|
str_u.MaximumLength = (USHORT) (Limit * sizeof(WCHAR));
|
|
|
|
if (Od2MBStringToUnicodeString(&str_u, &str_a, FALSE) == NO_ERROR) {
|
|
|
|
if (str_u.Length < str_u.MaximumLength) {
|
|
d[str_u.Length/sizeof(WCHAR)] = 0;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Od2MBStringToUnicodeString(&str_u, &str_a, TRUE) == NO_ERROR) {
|
|
|
|
RtlMoveMemory(d, str_u.Buffer, Limit * sizeof(WCHAR));
|
|
RtlFreeUnicodeString(&str_u);
|
|
|
|
} else {
|
|
d[0] = 0;
|
|
}
|
|
}
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
LPTSTR
|
|
ANSI2UTmemcpy(LPTSTR d, PCHAR s, ULONG count)
|
|
{
|
|
ANSI_STRING str_a;
|
|
UNICODE_STRING str_u;
|
|
|
|
if (s == NULL) {
|
|
return(d);
|
|
}
|
|
|
|
str_a.Buffer = s;
|
|
str_a.MaximumLength = str_a.Length = (USHORT) count;
|
|
|
|
str_u.Buffer = (PWSTR) d;
|
|
str_u.MaximumLength = 0xffff;
|
|
|
|
Od2MBStringToUnicodeString(&str_u, &str_a, FALSE);
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//Following are the LanMan API
|
|
//
|
|
//*****************************************************************************
|
|
|
|
// Most LanMan APIs are implemented with the following sequence:
|
|
// copy input from user's buffer to internal buffer while convertine ansi to unicode
|
|
// call win32 lanman api
|
|
// copy output from lanman api internal buffer to user's buffer
|
|
//
|
|
// for Enum type APIs, a loop is used to get as much data as possible.
|
|
|
|
|
|
|
|
// a small macro to copy a string from the internal net buffer to user's buffer
|
|
#define CopyUW2ANSI(d, s) \
|
|
StringLen = UWstrlen(s) + 1; \
|
|
CurEndOfBuffer -= StringLen; \
|
|
d = (char *)FLATTOFARPTR(CurEndOfBuffer); \
|
|
UW2ANSIstrcpy(CurEndOfBuffer, s);
|
|
|
|
|
|
APIRET
|
|
Od2QueryNPHInfo(
|
|
HPIPE hpipe,
|
|
PULONG pCollectDataTime,
|
|
PULONG pMaxCollectionCount
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
APIRET RetCode;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
PFILE_HANDLE hFileRecord;
|
|
FILE_PIPE_REMOTE_INFORMATION PipeRemoteInfoBuf;
|
|
LARGE_INTEGER LargeCollectDataTime;
|
|
#if DBG
|
|
PSZ RoutineName;
|
|
RoutineName = "Od2QueryNPHInfo";
|
|
#endif
|
|
|
|
AcquireFileLockShared(
|
|
#if DBG
|
|
RoutineName
|
|
#endif
|
|
);
|
|
|
|
//
|
|
// Check for invalid handle.
|
|
//
|
|
RetCode = DereferenceFileHandle(hpipe, &hFileRecord);
|
|
if (RetCode) {
|
|
ReleaseFileLockShared(
|
|
#if DBG
|
|
RoutineName
|
|
#endif
|
|
);
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
ReleaseFileLockShared(
|
|
#if DBG
|
|
RoutineName
|
|
#endif
|
|
);
|
|
|
|
if (hFileRecord->FileType != FILE_TYPE_NMPIPE) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( PIPES ) {
|
|
KdPrint(("DosQueryPNHState: File Type != NMPIPE hpipe %d\n",
|
|
hpipe));
|
|
}
|
|
#endif
|
|
return ERROR_BAD_PIPE;
|
|
}
|
|
|
|
Status = NtQueryInformationFile(hFileRecord->NtHandle,
|
|
&IoStatusBlock,
|
|
&PipeRemoteInfoBuf,
|
|
sizeof(FILE_PIPE_REMOTE_INFORMATION),
|
|
FilePipeRemoteInformation);
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( PIPES ) {
|
|
KdPrint(("DosQueryPNHState: NtqueryInformation error: Status %ld\n",
|
|
Status));
|
|
}
|
|
#endif
|
|
return ERROR_BAD_PIPE; // BUGBUG bogus
|
|
}
|
|
|
|
//
|
|
// Translate Information to OS/2 style values
|
|
//
|
|
|
|
LargeCollectDataTime = RtlExtendedLargeIntegerDivide(
|
|
PipeRemoteInfoBuf.CollectDataTime, 10000, NULL);
|
|
*pCollectDataTime = LargeCollectDataTime.LowPart;
|
|
*pMaxCollectionCount = PipeRemoteInfoBuf.MaximumCollectionCount;
|
|
|
|
return (NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16GetDCName(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszDomain,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer
|
|
)
|
|
{
|
|
WCHAR Server[UNCLEN];
|
|
WCHAR Domain[DNLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszDomain);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
ANSI2UWstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UWstrncpy(Domain, pszDomain, DNLEN);
|
|
|
|
rc = NetGetDCName(Server, Domain, &BufPtr);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
if (UWstrlen((LPWSTR) BufPtr) + 1 > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UW2ANSIstrcpy((PCHAR) pbBuffer, (LPWSTR) BufPtr);
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16HandleGetInfo(
|
|
IN HANDLE hHandle,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
NET_API_STATUS rc;
|
|
struct handle_info_1 *pOs2Info1;
|
|
ULONG CharTime;
|
|
ULONG CharCount;
|
|
|
|
if (sLevel != 1) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
try {
|
|
Od2ProbeForWrite(pcbTotalAvail,sizeof(*pcbTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
*pcbTotalAvail = sizeof(struct handle_info_1);
|
|
if (sizeof(struct handle_info_1) > cbBuffer) {
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
rc = Od2QueryNPHInfo(hHandle, &CharTime, &CharCount);
|
|
if (rc != NO_ERROR) {
|
|
return (rc);
|
|
}
|
|
pOs2Info1 = (struct handle_info_1*)pbBuffer;
|
|
pOs2Info1->hdli1_chartime = CharTime;
|
|
pOs2Info1->hdli1_charcount = (unsigned short)CharCount;
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ServerDiskEnum(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcEntriesRead,
|
|
OUT PUSHORT pcTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PWCHAR pInfo;
|
|
PCHAR pOs2Info;
|
|
ULONG OutBufSize;
|
|
DWORD EntriesRead;
|
|
DWORD i;
|
|
DWORD ResumeHandle;
|
|
DWORD TotalEntries;
|
|
ULONG StringLen;
|
|
int TotalAvailNotSet = TRUE;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForWrite(pcTotalAvail,sizeof(*pcTotalAvail),1);
|
|
Od2ProbeForWrite(pcEntriesRead,sizeof(*pcEntriesRead),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sLevel != 0) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
OutBufSize = cbBuffer;
|
|
ResumeHandle = 0;
|
|
pOs2Info = (PCHAR)pbBuffer;
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
rc = ERROR_MORE_DATA;
|
|
|
|
while (rc == ERROR_MORE_DATA) {
|
|
|
|
rc = NetServerDiskEnum(Server, 0, &BufPtr, PREFMAXLEN,
|
|
&EntriesRead, &TotalEntries, &ResumeHandle);
|
|
|
|
if ((rc != NO_ERROR) && (rc != ERROR_MORE_DATA)) {
|
|
return(rc);
|
|
}
|
|
|
|
if (TotalAvailNotSet) {
|
|
*pcTotalAvail = (USHORT) TotalEntries;
|
|
*pcEntriesRead = 0;
|
|
TotalAvailNotSet = FALSE;
|
|
}
|
|
|
|
pInfo = (PWCHAR) BufPtr;
|
|
|
|
for (i = 0; i < EntriesRead; i++) {
|
|
|
|
StringLen = UWstrlen(pInfo) + 1;
|
|
|
|
if ((StringLen + 1) > OutBufSize) {
|
|
if (cbBuffer > 0) { // if 0 length buffer, unable to return anything
|
|
*pOs2Info = '\0'; // The terminating NUL
|
|
}
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= StringLen;
|
|
|
|
UW2ANSIstrcpy(pOs2Info, pInfo);
|
|
|
|
pOs2Info += strlen(pOs2Info) + 1;
|
|
pInfo += StringLen;
|
|
|
|
(*pcEntriesRead)++;
|
|
}
|
|
*pOs2Info = '\0'; // The terminating NUL
|
|
NetApiBufferFree(BufPtr);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ServerEnum2(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcEntriesRead,
|
|
OUT PUSHORT pcTotalAvail,
|
|
IN ULONG flServerType,
|
|
IN PCHAR pszDomain
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR Domain[CNLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PSERVER_INFO_101 pInfo101;
|
|
struct server_info_0 *pOs2Info0;
|
|
struct server_info_1 *pOs2Info1;
|
|
PCHAR pEndOfBuffer;
|
|
ULONG StringLen;
|
|
DWORD ResumeHandle;
|
|
ULONG OutBufSize;
|
|
DWORD EntriesRead;
|
|
DWORD TotalEntries;
|
|
DWORD i;
|
|
int TotalAvailNotSet = TRUE;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszDomain);
|
|
Od2ProbeForWrite(pcTotalAvail,sizeof(*pcTotalAvail),1);
|
|
Od2ProbeForWrite(pcEntriesRead,sizeof(*pcEntriesRead),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
pEndOfBuffer = pbBuffer + cbBuffer;
|
|
OutBufSize = cbBuffer;
|
|
ResumeHandle = 0;
|
|
pOs2Info0 = (struct server_info_0 *)pbBuffer;
|
|
pOs2Info1 = (struct server_info_1 *)pbBuffer;
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(Domain, pszDomain, CNLEN);
|
|
rc = ERROR_MORE_DATA;
|
|
|
|
while (rc == ERROR_MORE_DATA) {
|
|
|
|
rc = NetServerEnum(Server, 101L, &BufPtr, PREFMAXLEN,
|
|
&EntriesRead, &TotalEntries,
|
|
flServerType, Domain, &ResumeHandle);
|
|
|
|
if ((rc != NO_ERROR) && (rc != ERROR_MORE_DATA)) {
|
|
return(rc);
|
|
}
|
|
|
|
if (TotalAvailNotSet) {
|
|
*pcTotalAvail = (USHORT) TotalEntries;
|
|
*pcEntriesRead = 0;
|
|
TotalAvailNotSet = FALSE;
|
|
}
|
|
|
|
pInfo101 = (PSERVER_INFO_101) BufPtr;
|
|
|
|
for (i = 0; i < EntriesRead; i++) {
|
|
if (sLevel == 0) {
|
|
if (sizeof(struct server_info_0) > OutBufSize) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= sizeof(struct server_info_0);
|
|
|
|
UT2ANSIstrncpy(pOs2Info0->sv0_name, (pInfo101 + i)->sv101_name, CNLEN_LM20);
|
|
pOs2Info0->sv0_name[CNLEN_LM20] = '\0';
|
|
pOs2Info0++;
|
|
}
|
|
else if (sLevel == 1) {
|
|
StringLen = UTstrlen((pInfo101 + i)->sv101_comment) + 1;
|
|
if ((sizeof(struct server_info_1) + StringLen) > OutBufSize) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= sizeof(struct server_info_1) + StringLen;
|
|
|
|
UT2ANSIstrncpy(pOs2Info1->sv1_name, (pInfo101 + i)->sv101_name, CNLEN_LM20);
|
|
pOs2Info1->sv1_name[CNLEN_LM20] = '\0';
|
|
pEndOfBuffer -= StringLen;
|
|
UT2ANSIstrcpy(pEndOfBuffer, (pInfo101 + i)->sv101_comment);
|
|
pOs2Info1->sv1_comment = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
|
|
pOs2Info1->sv1_version_major = (unsigned char)(pInfo101 + i)->sv101_version_major;
|
|
pOs2Info1->sv1_version_minor = (unsigned char)(pInfo101 + i)->sv101_version_minor;
|
|
pOs2Info1->sv1_type = (pInfo101 + i)->sv101_type;
|
|
pOs2Info1++;
|
|
}
|
|
(*pcEntriesRead)++;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ServerGetInfo(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
LPBYTE BufPtr1;
|
|
LPBYTE BufPtr2;
|
|
NET_API_STATUS rc;
|
|
PSERVER_INFO_102 pInfo102;
|
|
PSERVER_INFO_502 pInfo502;
|
|
struct server_info_0 *pOs2Info0;
|
|
struct server_info_1 *pOs2Info1;
|
|
struct server_info_2 *pOs2Info2;
|
|
struct server_info_3 *pOs2Info3;
|
|
PCHAR pStrings;
|
|
PCHAR pEndOfBuffer;
|
|
ULONG StringLen;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForWrite(pcbTotalAvail,sizeof(*pcbTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sLevel > 3) {
|
|
#if DBG
|
|
KdPrint(("NetServerGetInfo: non supported sLevel %d\n", sLevel));
|
|
#endif
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
rc = NetServerGetInfo(Server, 102L, &BufPtr1);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
rc = NetServerGetInfo(Server, 502L, &BufPtr2);
|
|
|
|
if (rc != NO_ERROR) {
|
|
NetApiBufferFree(BufPtr1);
|
|
return(rc);
|
|
}
|
|
|
|
RtlZeroMemory(pbBuffer, cbBuffer);
|
|
pInfo102 = (PSERVER_INFO_102) BufPtr1;
|
|
pInfo502 = (PSERVER_INFO_502) BufPtr2;
|
|
pEndOfBuffer = pbBuffer + cbBuffer;
|
|
pOs2Info0 = (struct server_info_0 *)pbBuffer;
|
|
pOs2Info1 = (struct server_info_1 *)pbBuffer;
|
|
pOs2Info2 = (struct server_info_2 *)pbBuffer;
|
|
pOs2Info3 = (struct server_info_3 *)pbBuffer;
|
|
|
|
switch (sLevel) {
|
|
|
|
case 0:
|
|
|
|
*pcbTotalAvail = (USHORT)(sizeof(struct server_info_0));
|
|
if (sizeof(struct server_info_0) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
|
|
pStrings = pbBuffer + sizeof(struct server_info_1);
|
|
|
|
StringLen = UTstrlen(pInfo102->sv102_comment) + 1;
|
|
*pcbTotalAvail = (USHORT)(StringLen + sizeof(struct server_info_1));
|
|
if (pStrings + StringLen > pEndOfBuffer) {
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
|
|
pStrings = pbBuffer + sizeof(struct server_info_2);
|
|
|
|
StringLen = UTstrlen(pInfo102->sv102_userpath) + 1;
|
|
*pcbTotalAvail = (USHORT)(StringLen + sizeof(struct server_info_2));
|
|
if (pStrings + StringLen > pEndOfBuffer) {
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
|
|
pStrings = pbBuffer + sizeof(struct server_info_3);
|
|
|
|
StringLen = UTstrlen(pInfo102->sv102_userpath) + 1;
|
|
*pcbTotalAvail = (USHORT)(StringLen + sizeof(struct server_info_3));
|
|
if (pStrings + StringLen > pEndOfBuffer) {
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
break;
|
|
}
|
|
|
|
switch (sLevel) {
|
|
|
|
case 3:
|
|
|
|
/*
|
|
pOs2Info3->sv3_auditedevents = pInfo403->sv403_auditedevents;
|
|
pOs2Info3->sv3_autoprofile = (unsigned short)pInfo403->sv403_autoprofile;
|
|
|
|
StringLen = UTstrlen(pInfo403->sv403_autopath) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo403->sv403_autopath);
|
|
pOs2Info3->sv3_autopath = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
*/
|
|
|
|
case 2:
|
|
|
|
/*
|
|
pOs2Info2->sv2_ulist_mtime = pInfo403->sv403_ulist_mtime;
|
|
pOs2Info2->sv2_glist_mtime = pInfo403->sv403_glist_mtime;
|
|
pOs2Info2->sv2_alist_mtime = pInfo403->sv403_alist_mtime;
|
|
*/
|
|
pOs2Info2->sv2_users = (unsigned short)pInfo102->sv102_users;
|
|
pOs2Info2->sv2_disc = (unsigned short)pInfo102->sv102_disc;
|
|
|
|
/*
|
|
StringLen = UTstrlen(pInfo403->sv403_alerts) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo403->sv403_alerts);
|
|
pOs2Info2->sv2_alerts = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
pOs2Info2->sv2_security = (unsigned short)pInfo403->sv403_security;
|
|
pOs2Info2->sv2_auditing = 0;
|
|
pOs2Info2->sv2_numadmin = (unsigned short)pInfo403->sv403_numadmin;
|
|
pOs2Info2->sv2_lanmask = (unsigned short)pInfo403->sv403_lanmask;
|
|
*/
|
|
pOs2Info2->sv2_hidden = (unsigned short)pInfo102->sv102_hidden;
|
|
pOs2Info2->sv2_announce = (unsigned short)pInfo102->sv102_announce;
|
|
pOs2Info2->sv2_anndelta = (unsigned short)pInfo102->sv102_anndelta;
|
|
|
|
/*
|
|
UT2ANSIstrncpy(pOs2Info2->sv2_guestacct, pInfo403->sv403_guestacct, UNLEN_LM20);
|
|
pOs2Info2->sv2_guestacct[UNLEN_LM20] = '\0';
|
|
*/
|
|
|
|
StringLen = UTstrlen(pInfo102->sv102_userpath) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo102->sv102_userpath);
|
|
pOs2Info2->sv2_userpath = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
// PQPQ pOs2Info2->sv2_chdevs = (unsigned short)pInfo403->sv403_chdevs;
|
|
pOs2Info2->sv2_chdevs = 100;
|
|
/*
|
|
pOs2Info2->sv2_chdevq = (unsigned short)pInfo403->sv403_chdevq;
|
|
pOs2Info2->sv2_chdevjobs = (unsigned short)pInfo403->sv403_chdevjobs;
|
|
pOs2Info2->sv2_connections = (unsigned short)pInfo403->sv403_connections;
|
|
pOs2Info2->sv2_shares = (unsigned short)pInfo403->sv403_shares;
|
|
pOs2Info2->sv2_openfiles = (unsigned short)pInfo403->sv403_openfiles;
|
|
*/
|
|
pOs2Info2->sv2_sessopens = (unsigned short)pInfo502->sv502_sessopens;
|
|
pOs2Info2->sv2_sessvcs = (unsigned short)pInfo502->sv502_sessvcs;
|
|
/*
|
|
pOs2Info2->sv2_sessreqs = (unsigned short)pInfo403->sv403_sessreqs;
|
|
*/
|
|
pOs2Info2->sv2_opensearch = (unsigned short)pInfo502->sv502_opensearch;
|
|
/*
|
|
pOs2Info2->sv2_activelocks = (unsigned short)pInfo403->sv403_activelocks;
|
|
pOs2Info2->sv2_numreqbuf = (unsigned short)pInfo403->sv403_numreqbuf;
|
|
*/
|
|
pOs2Info2->sv2_sizreqbuf = (unsigned short)pInfo502->sv502_sizreqbuf;
|
|
/*
|
|
pOs2Info2->sv2_numbigbuf = (unsigned short)pInfo403->sv403_numbigbuf;
|
|
pOs2Info2->sv2_numfiletasks= (unsigned short)pInfo403->sv403_numfiletasks;
|
|
pOs2Info2->sv2_alertsched = (unsigned short)pInfo403->sv403_alertsched;
|
|
pOs2Info2->sv2_erroralert = (unsigned short)pInfo403->sv403_erroralert;
|
|
pOs2Info2->sv2_logonalert = (unsigned short)pInfo403->sv403_logonalert;
|
|
pOs2Info2->sv2_accessalert = (unsigned short)pInfo403->sv403_accessalert;
|
|
pOs2Info2->sv2_diskalert = (unsigned short)pInfo403->sv403_diskalert;
|
|
pOs2Info2->sv2_netioalert = (unsigned short)pInfo403->sv403_netioalert;
|
|
pOs2Info2->sv2_maxauditsz = (unsigned short)pInfo403->sv403_maxauditsz;
|
|
|
|
StringLen = UTstrlen(pInfo403->sv403_srvheuristics) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo403->sv403_srvheuristics);
|
|
pOs2Info2->sv2_srvheuristics = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
*/
|
|
|
|
case 1:
|
|
|
|
StringLen = UTstrlen(pInfo102->sv102_comment) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo102->sv102_comment);
|
|
pOs2Info1->sv1_comment = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
pOs2Info1->sv1_version_major = (unsigned char)pInfo102->sv102_version_major;
|
|
pOs2Info1->sv1_version_minor = (unsigned char)pInfo102->sv102_version_minor;
|
|
pOs2Info1->sv1_type = (unsigned long)pInfo102->sv102_type;
|
|
|
|
case 0:
|
|
|
|
UT2ANSIstrncpy(pOs2Info0->sv0_name, pInfo102->sv102_name, CNLEN_LM20);
|
|
pOs2Info0->sv0_name[CNLEN_LM20] = '\0';
|
|
break;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ServiceControl(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszService,
|
|
IN ULONG fbOpCode,
|
|
IN ULONG fbArg,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR Service[SNLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PSERVICE_INFO_2 pInfo2;
|
|
struct service_info_2 *pOs2Info2;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszService);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
// OS/2 services are limited to 15 chars
|
|
// workaround an important NT service whose name is longer than 15 chars
|
|
|
|
if (!_stricmp(pszService, N_Workstation)) {
|
|
ANSI2UTstrcpy(Service, N_LanmanWorkstation);
|
|
}
|
|
if (!_stricmp(pszService, N_Server)) {
|
|
ANSI2UTstrcpy(Service, N_LanmanServer);
|
|
}
|
|
else {
|
|
ANSI2UTstrncpy(Service, pszService, SNLEN);
|
|
}
|
|
|
|
rc = NetServiceControl(Server, Service, fbOpCode, fbArg, &BufPtr);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
if (sizeof(struct service_info_2) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
pInfo2 = (PSERVICE_INFO_2) BufPtr;
|
|
pOs2Info2 = (struct service_info_2 *)pbBuffer;
|
|
UT2ANSIstrncpy(pOs2Info2->svci2_name, pInfo2->svci2_name, SNLEN_LM20);
|
|
pOs2Info2->svci2_name[SNLEN_LM20] = '\0';
|
|
if (!_stricmp(N_LanmanWorkstati, pOs2Info2->svci2_name)) {
|
|
strcpy(pOs2Info2->svci2_name, N_Workstation);
|
|
}
|
|
else if (!_stricmp(N_LanmanServer, pOs2Info2->svci2_name)) {
|
|
strcpy(pOs2Info2->svci2_name, N_Server);
|
|
}
|
|
UT2ANSIstrncpy(pOs2Info2->svci2_text, pInfo2->svci2_text, STXTLEN_LM20);
|
|
pOs2Info2->svci2_text[STXTLEN_LM20] = '\0';
|
|
pOs2Info2->svci2_status = (unsigned short)pInfo2->svci2_status;
|
|
pOs2Info2->svci2_code = (unsigned long)pInfo2->svci2_code;
|
|
pOs2Info2->svci2_pid = (unsigned short)pInfo2->svci2_pid;
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ServiceEnum(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcEntriesRead,
|
|
OUT PUSHORT pcTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PSERVICE_INFO_0 pInfo0;
|
|
PSERVICE_INFO_1 pInfo1;
|
|
PSERVICE_INFO_2 pInfo2;
|
|
struct service_info_0 *pOs2Info0;
|
|
struct service_info_1 *pOs2Info1;
|
|
struct service_info_2 *pOs2Info2;
|
|
DWORD ResumeHandle;
|
|
ULONG OutBufSize;
|
|
DWORD EntriesRead;
|
|
DWORD TotalEntries;
|
|
DWORD i;
|
|
int TotalAvailNotSet = TRUE;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForWrite(pcTotalAvail,sizeof(*pcTotalAvail),1);
|
|
Od2ProbeForWrite(pcEntriesRead,sizeof(*pcEntriesRead),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1) && (sLevel != 2)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
OutBufSize = cbBuffer;
|
|
ResumeHandle = 0;
|
|
pOs2Info0 = (struct service_info_0 *)pbBuffer;
|
|
pOs2Info1 = (struct service_info_1 *)pbBuffer;
|
|
pOs2Info2 = (struct service_info_2 *)pbBuffer;
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
rc = ERROR_MORE_DATA;
|
|
|
|
while (rc == ERROR_MORE_DATA) {
|
|
|
|
rc = NetServiceEnum(Server, sLevel, &BufPtr, PREFMAXLEN,
|
|
&EntriesRead, &TotalEntries, &ResumeHandle);
|
|
|
|
if ((rc != NO_ERROR) && (rc != ERROR_MORE_DATA)) {
|
|
return(rc);
|
|
}
|
|
|
|
if (TotalAvailNotSet) {
|
|
*pcTotalAvail = (USHORT) TotalEntries;
|
|
*pcEntriesRead = 0;
|
|
TotalAvailNotSet = FALSE;
|
|
}
|
|
|
|
for (i = 0; i < EntriesRead; i++) {
|
|
if (sLevel == 0) {
|
|
if (sizeof(struct service_info_0) > OutBufSize) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= sizeof(struct service_info_0);
|
|
|
|
pInfo0 = (PSERVICE_INFO_0) BufPtr + i;
|
|
UT2ANSIstrncpy(pOs2Info0->svci0_name, pInfo0->svci0_name, SNLEN_LM20);
|
|
pOs2Info0->svci0_name[SNLEN_LM20] = '\0';
|
|
if (!_stricmp(N_LanmanWorkstati, pOs2Info0->svci0_name)) {
|
|
strcpy(pOs2Info0->svci0_name, N_Workstation);
|
|
}
|
|
else if (!_stricmp(N_LanmanServer, pOs2Info0->svci0_name)) {
|
|
strcpy(pOs2Info0->svci0_name, N_Server);
|
|
}
|
|
|
|
pOs2Info0++;
|
|
}
|
|
else if (sLevel == 1) {
|
|
if (sizeof(struct service_info_1) > OutBufSize) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= sizeof(struct service_info_1);
|
|
|
|
pInfo1 = (PSERVICE_INFO_1) BufPtr + i;
|
|
UT2ANSIstrncpy(pOs2Info1->svci1_name, pInfo1->svci1_name, SNLEN_LM20);
|
|
pOs2Info1->svci1_name[SNLEN_LM20] = '\0';
|
|
if (!_stricmp(N_LanmanWorkstati, pOs2Info1->svci1_name)) {
|
|
strcpy(pOs2Info1->svci1_name, N_Workstation);
|
|
}
|
|
else if (!_stricmp(N_LanmanServer, pOs2Info1->svci1_name)) {
|
|
strcpy(pOs2Info1->svci1_name, N_Server);
|
|
}
|
|
|
|
pOs2Info1->svci1_status = (unsigned short)pInfo1->svci1_status;
|
|
pOs2Info1->svci1_code = (unsigned long)pInfo1->svci1_code;
|
|
pOs2Info1->svci1_pid = (unsigned short)pInfo1->svci1_pid;
|
|
|
|
pOs2Info1++;
|
|
}
|
|
else { /* sLevel == 2 */
|
|
if (sizeof(struct service_info_2) > OutBufSize) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= sizeof(struct service_info_2);
|
|
|
|
pInfo2 = (PSERVICE_INFO_2) BufPtr + i;
|
|
UT2ANSIstrncpy(pOs2Info2->svci2_name, pInfo2->svci2_name, SNLEN_LM20);
|
|
pOs2Info2->svci2_name[SNLEN_LM20] = '\0';
|
|
if (!_stricmp(N_LanmanWorkstati, pOs2Info2->svci2_name)) {
|
|
strcpy(pOs2Info2->svci2_name, N_Workstation);
|
|
}
|
|
else if (!_stricmp(N_LanmanServer, pOs2Info2->svci2_name)) {
|
|
strcpy(pOs2Info2->svci2_name, N_Server);
|
|
}
|
|
|
|
pOs2Info2->svci2_status = (unsigned short)pInfo2->svci2_status;
|
|
pOs2Info2->svci2_code = (unsigned long)pInfo2->svci2_code;
|
|
pOs2Info2->svci2_pid = (unsigned short)pInfo2->svci2_pid;
|
|
|
|
UT2ANSIstrncpy(pOs2Info2->svci2_text, pInfo2->svci2_text, STXTLEN_LM20);
|
|
pOs2Info2->svci2_name[STXTLEN_LM20] = '\0';
|
|
|
|
pOs2Info2++;
|
|
}
|
|
(*pcEntriesRead)++;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
}
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ServiceGetInfo(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszService,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR Service[SNLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PSERVICE_INFO_2 pInfo2;
|
|
struct service_info_2 *pOs2Info2;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszService);
|
|
Od2ProbeForWrite(pcbTotalAvail,sizeof(*pcbTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1) && (sLevel != 2)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
// OS/2 services are limited to 15 chars
|
|
// workaround an important NT service whose name is longer than 15 chars
|
|
|
|
if (!_stricmp(pszService, N_Workstation)) {
|
|
ANSI2UTstrcpy(Service, N_LanmanWorkstation);
|
|
}
|
|
if (!_stricmp(pszService, N_Server)) {
|
|
ANSI2UTstrcpy(Service, N_LanmanServer);
|
|
}
|
|
else {
|
|
ANSI2UTstrncpy(Service, pszService, SNLEN);
|
|
}
|
|
|
|
rc = NetServiceGetInfo(Server, Service, 2L, &BufPtr);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
pOs2Info2 = (struct service_info_2 *)pbBuffer;
|
|
pInfo2 = (PSERVICE_INFO_2) BufPtr;
|
|
|
|
switch (sLevel) {
|
|
case 0:
|
|
*pcbTotalAvail = (USHORT)sizeof(struct service_info_0);
|
|
break;
|
|
|
|
case 1:
|
|
*pcbTotalAvail = (USHORT)sizeof(struct service_info_1);
|
|
break;
|
|
|
|
case 2:
|
|
*pcbTotalAvail = (USHORT)sizeof(struct service_info_2);
|
|
break;
|
|
}
|
|
|
|
if (sizeof(struct service_info_0) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UT2ANSIstrncpy(pOs2Info2->svci2_name, pInfo2->svci2_name, SNLEN_LM20);
|
|
pOs2Info2->svci2_name[SNLEN_LM20] = '\0';
|
|
if (!_stricmp(N_LanmanWorkstati, pOs2Info2->svci2_name)) {
|
|
strcpy(pOs2Info2->svci2_name, N_Workstation);
|
|
}
|
|
else if (!_stricmp(N_LanmanServer, pOs2Info2->svci2_name)) {
|
|
strcpy(pOs2Info2->svci2_name, N_Server);
|
|
}
|
|
|
|
if (sLevel >= 1) {
|
|
if (sizeof(struct service_info_1) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
pOs2Info2->svci2_status = (unsigned short)pInfo2->svci2_status;
|
|
pOs2Info2->svci2_code = (unsigned long)pInfo2->svci2_code;
|
|
pOs2Info2->svci2_pid = (unsigned short)pInfo2->svci2_pid;
|
|
}
|
|
|
|
if (sLevel >= 2) {
|
|
if (sizeof(struct service_info_2) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UT2ANSIstrncpy(pOs2Info2->svci2_text, pInfo2->svci2_text, STXTLEN_LM20);
|
|
pOs2Info2->svci2_text[STXTLEN_LM20] = '\0';
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ServiceInstall(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszService,
|
|
IN PCHAR pszCmdArgs,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR Service[SNLEN];
|
|
TCHAR *CmdArgs;
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PSERVICE_INFO_2 pInfo2;
|
|
struct service_info_2 *pOs2Info2;
|
|
DWORD Argc;
|
|
DWORD TotalSizeOfStrings;
|
|
PCHAR pStrings;
|
|
PCHAR pszTmpCmdArgs;
|
|
LPTSTR StartOfString;
|
|
ULONG i;
|
|
LPTSTR Argv[64];
|
|
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszService);
|
|
PROBE_STRING(pszCmdArgs);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sizeof(struct service_info_2) > cbBuffer) {
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
pOs2Info2 = (struct service_info_2 *)pbBuffer;
|
|
|
|
if (pszCmdArgs == NULL) {
|
|
pszTmpCmdArgs = "";
|
|
}
|
|
else {
|
|
pszTmpCmdArgs = pszCmdArgs;
|
|
}
|
|
|
|
Argc = 0;
|
|
pStrings = pszTmpCmdArgs;
|
|
|
|
while (*pStrings) {
|
|
pStrings += strlen(pStrings) + 1;
|
|
Argc++;
|
|
}
|
|
pStrings++; // for the terminating nul character
|
|
|
|
if (Argc > 64) {
|
|
return(ERROR_ACCESS_DENIED);
|
|
}
|
|
|
|
TotalSizeOfStrings = pStrings - pszTmpCmdArgs;
|
|
|
|
CmdArgs = (TCHAR *) RtlAllocateHeap(Od2Heap, 0, TotalSizeOfStrings * sizeof(TCHAR));
|
|
|
|
if (CmdArgs == NULL) {
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
// OS/2 services are limited to 15 chars
|
|
// workaround an important NT service whose name is longer than 15 chars
|
|
|
|
if (!_stricmp(pszService, N_Workstation)) {
|
|
ANSI2UTstrcpy(Service, N_LanmanWorkstation);
|
|
}
|
|
if (!_stricmp(pszService, N_Server)) {
|
|
ANSI2UTstrcpy(Service, N_LanmanServer);
|
|
}
|
|
else {
|
|
ANSI2UTstrncpy(Service, pszService, SNLEN);
|
|
}
|
|
|
|
ANSI2UTmemcpy(CmdArgs, pszTmpCmdArgs, TotalSizeOfStrings);
|
|
|
|
StartOfString = CmdArgs;
|
|
for (i = 0; i < Argc; i++) {
|
|
Argv[i] = StartOfString;
|
|
while (*StartOfString++ != L'\0') {
|
|
;
|
|
}
|
|
}
|
|
|
|
rc = NetServiceInstall(Server, Service, Argc, Argv, &BufPtr);
|
|
|
|
RtlFreeHeap(Od2Heap, 0, CmdArgs);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
pInfo2 = (PSERVICE_INFO_2) BufPtr;
|
|
|
|
UT2ANSIstrncpy(pOs2Info2->svci2_name, pInfo2->svci2_name, SNLEN_LM20);
|
|
pOs2Info2->svci2_name[SNLEN_LM20] = '\0';
|
|
if (!_stricmp(N_LanmanWorkstati, pOs2Info2->svci2_name)) {
|
|
strcpy(pOs2Info2->svci2_name, N_Workstation);
|
|
}
|
|
else if (!_stricmp(N_LanmanServer, pOs2Info2->svci2_name)) {
|
|
strcpy(pOs2Info2->svci2_name, N_Server);
|
|
}
|
|
pOs2Info2->svci2_status = (unsigned short)pInfo2->svci2_status;
|
|
pOs2Info2->svci2_code = (unsigned long)pInfo2->svci2_code;
|
|
pOs2Info2->svci2_pid = (unsigned short)pInfo2->svci2_pid;
|
|
UT2ANSIstrncpy(pOs2Info2->svci2_text, pInfo2->svci2_text, STXTLEN_LM20);
|
|
pOs2Info2->svci2_text[STXTLEN_LM20] = '\0';
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ShareEnum(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcEntriesRead,
|
|
OUT PUSHORT pcTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PSHARE_INFO_2 pInfo2;
|
|
struct share_info_0 *pOs2Info0;
|
|
struct share_info_1 *pOs2Info1;
|
|
struct share_info_2 *pOs2Info2;
|
|
PCHAR pEndOfBuffer;
|
|
ULONG StringLen;
|
|
DWORD ResumeHandle;
|
|
ULONG OutBufSize;
|
|
DWORD EntriesRead;
|
|
DWORD TotalEntries;
|
|
DWORD i;
|
|
int TotalAvailNotSet = TRUE;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForWrite(pcTotalAvail,sizeof(*pcTotalAvail),1);
|
|
Od2ProbeForWrite(pcEntriesRead,sizeof(*pcEntriesRead),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1) && (sLevel != 2)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
pEndOfBuffer = pbBuffer + cbBuffer;
|
|
OutBufSize = cbBuffer;
|
|
ResumeHandle = 0;
|
|
pOs2Info0 = (struct share_info_0 *)pbBuffer;
|
|
pOs2Info1 = (struct share_info_1 *)pbBuffer;
|
|
pOs2Info2 = (struct share_info_2 *)pbBuffer;
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
rc = ERROR_MORE_DATA;
|
|
|
|
while (rc == ERROR_MORE_DATA) {
|
|
|
|
rc = NetShareEnum(Server, 2L, &BufPtr, PREFMAXLEN,
|
|
&EntriesRead, &TotalEntries, &ResumeHandle);
|
|
|
|
if ((rc != NO_ERROR) && (rc != ERROR_MORE_DATA)) {
|
|
return(rc);
|
|
}
|
|
|
|
if (TotalAvailNotSet) {
|
|
*pcTotalAvail = (USHORT) TotalEntries;
|
|
*pcEntriesRead = 0;
|
|
TotalAvailNotSet = FALSE;
|
|
}
|
|
|
|
for (i = 0; i < EntriesRead; i++) {
|
|
pInfo2 = (PSHARE_INFO_2) BufPtr + i;
|
|
if (sLevel == 0) {
|
|
if (sizeof(struct share_info_0) > OutBufSize) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= sizeof(struct share_info_0);
|
|
|
|
UT2ANSIstrncpy(pOs2Info0->shi0_netname, pInfo2->shi2_netname, NNLEN_LM20);
|
|
pOs2Info0->shi0_netname[NNLEN_LM20] = '\0';
|
|
pOs2Info0++;
|
|
}
|
|
else if (sLevel == 1) {
|
|
StringLen = UTstrlen(pInfo2->shi2_remark) + 1;
|
|
if ((sizeof(struct share_info_1) + StringLen) > OutBufSize) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= sizeof(struct share_info_1) + StringLen;
|
|
|
|
UT2ANSIstrncpy(pOs2Info1->shi1_netname, pInfo2->shi2_netname, NNLEN_LM20);
|
|
pOs2Info1->shi1_netname[NNLEN_LM20] = '\0';
|
|
pEndOfBuffer -= StringLen;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo2->shi2_remark);
|
|
pOs2Info1->shi1_remark = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
|
|
pOs2Info1->shi1_type = (unsigned short)pInfo2->shi2_type;
|
|
pOs2Info1++;
|
|
}
|
|
else {
|
|
StringLen = UTstrlen(pInfo2->shi2_remark) + 1 +
|
|
UTstrlen(pInfo2->shi2_path) + 1 ;
|
|
if ((sizeof(struct share_info_2) + StringLen) > OutBufSize) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
OutBufSize -= sizeof(struct share_info_2) + StringLen;
|
|
|
|
UT2ANSIstrncpy(pOs2Info2->shi2_netname, pInfo2->shi2_netname, NNLEN_LM20);
|
|
pOs2Info2->shi2_netname[NNLEN_LM20] = '\0';
|
|
UT2ANSIstrncpy(pOs2Info2->shi2_passwd, pInfo2->shi2_passwd, SHPWLEN_LM20);
|
|
pOs2Info2->shi2_passwd[SHPWLEN_LM20] = '\0';
|
|
pEndOfBuffer -= UTstrlen(pInfo2->shi2_remark) + 1;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo2->shi2_remark);
|
|
pOs2Info2->shi2_remark = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
pEndOfBuffer -= UTstrlen(pInfo2->shi2_path) + 1;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo2->shi2_path);
|
|
pOs2Info2->shi2_path = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
|
|
pOs2Info2->shi2_type = (unsigned short)pInfo2->shi2_type;
|
|
pOs2Info2->shi2_permissions = (unsigned short)pInfo2->shi2_permissions;
|
|
pOs2Info2->shi2_max_uses = (unsigned short)pInfo2->shi2_max_uses;
|
|
pOs2Info2->shi2_current_uses = (unsigned short)pInfo2->shi2_current_uses;
|
|
pOs2Info2++;
|
|
}
|
|
(*pcEntriesRead)++;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
}
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ShareGetInfo(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszNetName,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR NetName[NNLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PSHARE_INFO_2 pInfo2;
|
|
PCHAR pEndOfBuffer;
|
|
ULONG TotalStringLen;
|
|
ULONG StringLen;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszNetName);
|
|
Od2ProbeForWrite(pcbTotalAvail,sizeof(*pcbTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1) && (sLevel != 3)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(NetName, pszNetName, NNLEN);
|
|
|
|
rc = NetShareGetInfo(Server, NetName, 2L, &BufPtr);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
pEndOfBuffer = pbBuffer;
|
|
pInfo2 = (PSHARE_INFO_2) BufPtr;
|
|
|
|
if (sLevel == 0) {
|
|
struct share_info_0 *pOs2Info0;
|
|
|
|
*pcbTotalAvail = (USHORT)sizeof(struct share_info_0);
|
|
if (sizeof(struct share_info_0) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
pOs2Info0 = (struct share_info_0 *)pbBuffer;
|
|
UT2ANSIstrncpy(pOs2Info0->shi0_netname, pInfo2->shi2_netname, NNLEN_LM20);
|
|
pOs2Info0->shi0_netname[NNLEN_LM20] = '\0';
|
|
}
|
|
else if (sLevel == 1) {
|
|
struct share_info_1 *pOs2Info1;
|
|
|
|
TotalStringLen = UTstrlen(pInfo2->shi2_remark) + 1;
|
|
*pcbTotalAvail = (USHORT)(TotalStringLen + sizeof(struct share_info_1));
|
|
if ((sizeof(struct share_info_1) + TotalStringLen) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
pOs2Info1 = (struct share_info_1 *)pbBuffer;
|
|
UT2ANSIstrncpy(pOs2Info1->shi1_netname, pInfo2->shi2_netname, NNLEN_LM20);
|
|
pOs2Info1->shi1_netname[NNLEN_LM20] = '\0';
|
|
pEndOfBuffer += sizeof(struct share_info_1);
|
|
StringLen = UTstrlen(pInfo2->shi2_remark) + 1;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo2->shi2_remark);
|
|
pOs2Info1->shi1_remark = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
pEndOfBuffer += StringLen;
|
|
|
|
pOs2Info1->shi1_type = (unsigned short)pInfo2->shi2_type;
|
|
}
|
|
else {
|
|
struct share_info_2 *pOs2Info2;
|
|
|
|
TotalStringLen = UTstrlen(pInfo2->shi2_remark) + 1 +
|
|
UTstrlen(pInfo2->shi2_path) + 1 ;
|
|
*pcbTotalAvail = (USHORT)(TotalStringLen + sizeof(struct share_info_2));
|
|
if ((sizeof(struct share_info_2) + TotalStringLen) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
pOs2Info2 = (struct share_info_2 *)pbBuffer;
|
|
UT2ANSIstrncpy(pOs2Info2->shi2_netname, pInfo2->shi2_netname, NNLEN_LM20);
|
|
pOs2Info2->shi2_netname[NNLEN_LM20] = '\0';
|
|
UT2ANSIstrncpy(pOs2Info2->shi2_passwd, pInfo2->shi2_passwd, SHPWLEN_LM20);
|
|
pOs2Info2->shi2_passwd[SHPWLEN_LM20] = '\0';
|
|
pEndOfBuffer += sizeof(struct share_info_2);
|
|
StringLen = UTstrlen(pInfo2->shi2_remark) + 1;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo2->shi2_remark);
|
|
pOs2Info2->shi2_remark = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
pEndOfBuffer += StringLen;
|
|
StringLen = UTstrlen(pInfo2->shi2_path) + 1;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo2->shi2_path);
|
|
pOs2Info2->shi2_path = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
pEndOfBuffer += StringLen;
|
|
|
|
pOs2Info2->shi2_type = (unsigned short)pInfo2->shi2_type;
|
|
pOs2Info2->shi2_permissions = (unsigned short)pInfo2->shi2_permissions;
|
|
pOs2Info2->shi2_max_uses = (unsigned short)pInfo2->shi2_max_uses;
|
|
pOs2Info2->shi2_current_uses = (unsigned short)pInfo2->shi2_current_uses;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16UseAdd(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
IN PCHAR pbBuffer,
|
|
IN ULONG cbBuffer
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR Local[DEVLEN];
|
|
TCHAR Remote[RMLEN];
|
|
TCHAR Password[PWLEN];
|
|
USE_INFO_1 Info1;
|
|
struct use_info_1 *pInfo1;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForRead(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sLevel != 1) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
if (cbBuffer < sizeof(struct use_info_1)) {
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
pInfo1 = (struct use_info_1 *) pbBuffer;
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(Local, pInfo1->ui1_local, DEVLEN);
|
|
Info1.ui1_local = Local;
|
|
ANSI2UTstrncpy(Remote, FARPTRTOFLAT(pInfo1->ui1_remote), RMLEN);
|
|
Info1.ui1_remote = Remote;
|
|
|
|
if (pInfo1->ui1_password == NULL) {
|
|
Info1.ui1_password = NULL;
|
|
}
|
|
else {
|
|
ANSI2UTstrncpy(Password, FARPTRTOFLAT(pInfo1->ui1_password), PWLEN);
|
|
Info1.ui1_password = Password;
|
|
}
|
|
|
|
Info1.ui1_status = pInfo1->ui1_status;
|
|
Info1.ui1_asg_type = pInfo1->ui1_asg_type;
|
|
Info1.ui1_refcount = pInfo1->ui1_refcount;
|
|
Info1.ui1_usecount = pInfo1->ui1_usecount;
|
|
|
|
return (NetUseAdd(Server, sLevel, (LPBYTE)&Info1, NULL));
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16UseDel(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszUseName,
|
|
IN ULONG usForce
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR UseName[RMLEN];
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszUseName);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(UseName, pszUseName, RMLEN);
|
|
|
|
return (NetUseDel(Server, UseName, usForce));
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16UseEnum(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcEntriesRead,
|
|
OUT PUSHORT pcTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
struct use_info_0 *pOs2Info0;
|
|
struct use_info_1 *pOs2Info1;
|
|
PUSE_INFO_0 pInfo0;
|
|
PUSE_INFO_1 pInfo1;
|
|
DWORD EntriesRead;
|
|
DWORD ResumeHandle;
|
|
DWORD TotalAvail;
|
|
DWORD i;
|
|
ULONG RemoteNameLen;
|
|
ULONG PasswordNameLen;
|
|
PCHAR CurEndOfBuffer;
|
|
ULONG OutBufSize;
|
|
int TotalAvailNotSet = TRUE;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForWrite(pcEntriesRead,sizeof(*pcEntriesRead),1);
|
|
Od2ProbeForWrite(pcTotalAvail,sizeof(*pcTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
OutBufSize = cbBuffer;
|
|
CurEndOfBuffer = pbBuffer + cbBuffer;
|
|
pOs2Info0 = (struct use_info_0 *)pbBuffer;
|
|
pOs2Info1 = (struct use_info_1 *)pbBuffer;
|
|
|
|
ResumeHandle = 0;
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
rc = ERROR_MORE_DATA;
|
|
|
|
while (rc == ERROR_MORE_DATA) {
|
|
|
|
rc = NetUseEnum(Server, sLevel, &BufPtr, PREFMAXLEN,
|
|
&EntriesRead, &TotalAvail, &ResumeHandle);
|
|
|
|
if ((rc != NO_ERROR) && (rc != ERROR_MORE_DATA)) {
|
|
return(rc);
|
|
}
|
|
|
|
if (TotalAvailNotSet) {
|
|
*pcTotalAvail = (USHORT) TotalAvail;
|
|
*pcEntriesRead = 0;
|
|
TotalAvailNotSet = FALSE;
|
|
}
|
|
|
|
for (i = 0; i < EntriesRead; i++) {
|
|
if (sLevel == 0) {
|
|
pInfo0 = (PUSE_INFO_0) BufPtr + i;
|
|
RemoteNameLen = UTstrlen(pInfo0->ui0_remote) + 1;
|
|
if ((sizeof(struct use_info_0) + RemoteNameLen) > OutBufSize ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
|
|
OutBufSize -= sizeof(struct use_info_0) + RemoteNameLen;
|
|
UT2ANSIstrncpy(pOs2Info0->ui0_local, pInfo0->ui0_local, DEVLEN_LM20);
|
|
pOs2Info0->ui0_local[DEVLEN_LM20] = '\0';
|
|
CurEndOfBuffer -= RemoteNameLen;
|
|
UT2ANSIstrcpy(CurEndOfBuffer, pInfo0->ui0_remote);
|
|
pOs2Info0->ui0_remote = (char *)FLATTOFARPTR(CurEndOfBuffer);
|
|
|
|
pOs2Info0++;
|
|
}
|
|
else {
|
|
pInfo1 = (PUSE_INFO_1) BufPtr + i;
|
|
RemoteNameLen = UTstrlen(pInfo1->ui1_remote) + 1;
|
|
PasswordNameLen = UTstrlen(pInfo1->ui1_password) + 1;
|
|
if ((sizeof(struct use_info_1) + RemoteNameLen + PasswordNameLen) > OutBufSize ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
|
|
OutBufSize -= sizeof(struct use_info_1) + RemoteNameLen + PasswordNameLen;
|
|
UT2ANSIstrncpy(pOs2Info1->ui1_local, pInfo1->ui1_local, DEVLEN_LM20);
|
|
pOs2Info1->ui1_local[DEVLEN_LM20] = '\0';
|
|
CurEndOfBuffer -= RemoteNameLen;
|
|
UT2ANSIstrcpy(CurEndOfBuffer, pInfo1->ui1_remote);
|
|
pOs2Info1->ui1_remote = (char *)FLATTOFARPTR(CurEndOfBuffer);
|
|
CurEndOfBuffer -= PasswordNameLen;
|
|
UT2ANSIstrcpy(CurEndOfBuffer, pInfo1->ui1_password);
|
|
pOs2Info1->ui1_password = (char *)FLATTOFARPTR(CurEndOfBuffer);
|
|
pOs2Info1->ui1_status = (unsigned short)pInfo1->ui1_status;
|
|
pOs2Info1->ui1_asg_type = (short)pInfo1->ui1_asg_type;
|
|
pOs2Info1->ui1_refcount = (unsigned short)pInfo1->ui1_refcount;
|
|
pOs2Info1->ui1_usecount = (unsigned short)pInfo1->ui1_usecount;
|
|
|
|
pOs2Info1++;
|
|
}
|
|
(*pcEntriesRead)++;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16UseGetInfo(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszUseName,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR UseName[RMLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PCHAR pEndOfBuffer;
|
|
ULONG TotalStringLen;
|
|
ULONG StringLen;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszUseName);
|
|
Od2ProbeForWrite(pcbTotalAvail,sizeof(*pcbTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(UseName, pszUseName, RMLEN);
|
|
|
|
rc = NetUseGetInfo(Server, UseName, sLevel, &BufPtr);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
pEndOfBuffer = pbBuffer;
|
|
|
|
if (sLevel == 0) {
|
|
PUSE_INFO_0 pInfo0 = (PUSE_INFO_0) BufPtr;
|
|
struct use_info_0 *pOs2Info0 = (struct use_info_0 *)pbBuffer;
|
|
|
|
TotalStringLen = UTstrlen(pInfo0->ui0_remote) + 1;
|
|
*pcbTotalAvail = (USHORT)(TotalStringLen + sizeof(struct use_info_0));
|
|
if ((ULONG) *pcbTotalAvail > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UT2ANSIstrncpy(pOs2Info0->ui0_local, pInfo0->ui0_local, DEVLEN_LM20);
|
|
pOs2Info0->ui0_local[DEVLEN_LM20] = '\0';
|
|
pEndOfBuffer += sizeof(struct use_info_0);
|
|
StringLen = TotalStringLen;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo0->ui0_remote);
|
|
pOs2Info0->ui0_remote = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
}
|
|
else {
|
|
PUSE_INFO_1 pInfo1 = (PUSE_INFO_1) BufPtr;
|
|
struct use_info_1 *pOs2Info1 = (struct use_info_1 *)pbBuffer;
|
|
|
|
TotalStringLen = UTstrlen(pInfo1->ui1_remote) + 1 +
|
|
UTstrlen(pInfo1->ui1_password) + 1;
|
|
*pcbTotalAvail = (USHORT)(TotalStringLen + sizeof(struct use_info_1));
|
|
if ((ULONG) *pcbTotalAvail > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UT2ANSIstrncpy(pOs2Info1->ui1_local, pInfo1->ui1_local, DEVLEN_LM20);
|
|
pOs2Info1->ui1_local[DEVLEN_LM20] = '\0';
|
|
pEndOfBuffer += sizeof(struct use_info_1);
|
|
StringLen = UTstrlen(pInfo1->ui1_remote) + 1;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo1->ui1_remote);
|
|
pOs2Info1->ui1_remote = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
pEndOfBuffer += StringLen;
|
|
StringLen = UTstrlen(pInfo1->ui1_password) + 1;
|
|
UT2ANSIstrcpy(pEndOfBuffer, pInfo1->ui1_password);
|
|
pOs2Info1->ui1_password = (char *)FLATTOFARPTR(pEndOfBuffer);
|
|
pEndOfBuffer += StringLen;
|
|
|
|
pOs2Info1->ui1_status = (unsigned short)pInfo1->ui1_status;
|
|
pOs2Info1->ui1_asg_type = (short)pInfo1->ui1_asg_type;
|
|
pOs2Info1->ui1_refcount = (unsigned short)pInfo1->ui1_refcount;
|
|
pOs2Info1->ui1_usecount = (unsigned short)pInfo1->ui1_usecount;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
return(rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16UserEnum(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcEntriesRead,
|
|
OUT PUSHORT pcTotalAvail
|
|
)
|
|
{
|
|
WCHAR Server[UNCLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
struct user_info_0 *pOs2Info0;
|
|
struct user_info_1 *pOs2Info1;
|
|
struct user_info_2 *pOs2Info2;
|
|
struct user_info_10 *pOs2Info10;
|
|
PUSER_INFO_0 pInfo0;
|
|
PUSER_INFO_1 pInfo1;
|
|
PUSER_INFO_2 pInfo2;
|
|
PUSER_INFO_10 pInfo10;
|
|
PCHAR CurEndOfBuffer;
|
|
ULONG StringLen;
|
|
DWORD EntriesRead;
|
|
DWORD ResumeHandle;
|
|
DWORD TotalEntries;
|
|
ULONG OutBufSize;
|
|
int TotalAvailNotSet = TRUE;
|
|
DWORD i;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForWrite(pcEntriesRead,sizeof(*pcEntriesRead),1);
|
|
Od2ProbeForWrite(pcTotalAvail,sizeof(*pcTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1) && (sLevel != 2) &&
|
|
(sLevel != 10)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
OutBufSize = cbBuffer;
|
|
CurEndOfBuffer = pbBuffer + cbBuffer;
|
|
ResumeHandle = 0;
|
|
pOs2Info0 = (struct user_info_0 *)pbBuffer;
|
|
pOs2Info1 = (struct user_info_1 *)pbBuffer;
|
|
pOs2Info2 = (struct user_info_2 *)pbBuffer;
|
|
pOs2Info10 = (struct user_info_10 *)pbBuffer;
|
|
|
|
|
|
ANSI2UWstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
rc = ERROR_MORE_DATA;
|
|
|
|
while (rc == ERROR_MORE_DATA) {
|
|
|
|
rc = NetUserEnum(Server, sLevel,
|
|
FILTER_TEMP_DUPLICATE_ACCOUNT | FILTER_NORMAL_ACCOUNT,
|
|
&BufPtr,
|
|
PREFMAXLEN,
|
|
&EntriesRead, &TotalEntries, &ResumeHandle);
|
|
|
|
if ((rc != NO_ERROR) && (rc != ERROR_MORE_DATA)) {
|
|
return(rc);
|
|
}
|
|
|
|
if (TotalAvailNotSet) {
|
|
*pcTotalAvail = (USHORT) TotalEntries;
|
|
*pcEntriesRead = 0;
|
|
TotalAvailNotSet = FALSE;
|
|
}
|
|
|
|
for (i = 0; i < EntriesRead; i++) {
|
|
if (sLevel == 0) {
|
|
pInfo0 = (PUSER_INFO_0) BufPtr + i;
|
|
if (sizeof(struct user_info_0) > OutBufSize ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
|
|
OutBufSize -= sizeof(struct user_info_0);
|
|
UW2ANSIstrncpy(pOs2Info0->usri0_name, pInfo0->usri0_name, UNLEN_LM20);
|
|
pOs2Info0->usri0_name[UNLEN_LM20] = '\0';
|
|
|
|
pOs2Info0++;
|
|
}
|
|
else if (sLevel == 1) {
|
|
pInfo1 = (PUSER_INFO_1) BufPtr + i;
|
|
StringLen = sizeof(struct user_info_1) +
|
|
UWstrlen(pInfo1->usri1_home_dir) + 1 +
|
|
UWstrlen(pInfo1->usri1_comment) + 1 +
|
|
UWstrlen(pInfo1->usri1_script_path) + 1;
|
|
if (StringLen > OutBufSize ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
|
|
OutBufSize -= StringLen;
|
|
UW2ANSIstrncpy(pOs2Info1->usri1_name, pInfo1->usri1_name, UNLEN_LM20);
|
|
pOs2Info1->usri1_name[UNLEN_LM20] = '\0';
|
|
UW2ANSIstrncpy(pOs2Info1->usri1_password, pInfo1->usri1_password, ENCRYPTED_PWLEN_LM20);
|
|
pOs2Info1->usri1_password[ENCRYPTED_PWLEN_LM20] = '\0';
|
|
|
|
pOs2Info1->usri1_password_age = (long)pInfo1->usri1_password_age;
|
|
pOs2Info1->usri1_priv = (unsigned short)pInfo1->usri1_priv;
|
|
|
|
CopyUW2ANSI(pOs2Info1->usri1_home_dir, pInfo1->usri1_home_dir);
|
|
CopyUW2ANSI(pOs2Info1->usri1_comment, pInfo1->usri1_comment);
|
|
CopyUW2ANSI(pOs2Info1->usri1_script_path, pInfo1->usri1_script_path);
|
|
|
|
pOs2Info1++;
|
|
}
|
|
else if (sLevel == 2) {
|
|
pInfo2 = (PUSER_INFO_2) BufPtr + i;
|
|
StringLen = sizeof(struct user_info_2) +
|
|
UWstrlen(pInfo2->usri2_home_dir) + 1 +
|
|
UWstrlen(pInfo2->usri2_comment) + 1 +
|
|
UWstrlen(pInfo2->usri2_script_path) + 1 +
|
|
UWstrlen(pInfo2->usri2_full_name) + 1 +
|
|
UWstrlen(pInfo2->usri2_usr_comment) + 1 +
|
|
UWstrlen(pInfo2->usri2_parms) + 1 +
|
|
UWstrlen(pInfo2->usri2_workstations) + 1 +
|
|
strlen(pInfo2->usri2_logon_hours) + 1 +
|
|
UWstrlen(pInfo2->usri2_logon_server) + 1;
|
|
if (StringLen > OutBufSize ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
|
|
OutBufSize -= StringLen;
|
|
UW2ANSIstrncpy(pOs2Info2->usri2_name, pInfo2->usri2_name, UNLEN_LM20);
|
|
pOs2Info2->usri2_name[UNLEN_LM20] = '\0';
|
|
UW2ANSIstrncpy(pOs2Info2->usri2_password, pInfo2->usri2_password, ENCRYPTED_PWLEN_LM20);
|
|
pOs2Info2->usri2_password[ENCRYPTED_PWLEN_LM20] = '\0';
|
|
pOs2Info2->usri2_password_age = (long)pInfo2->usri2_password_age;
|
|
pOs2Info2->usri2_priv = (unsigned short)pInfo2->usri2_priv;
|
|
|
|
CopyUW2ANSI(pOs2Info2->usri2_home_dir, pInfo2->usri2_home_dir);
|
|
CopyUW2ANSI(pOs2Info2->usri2_comment, pInfo2->usri2_comment);
|
|
CopyUW2ANSI(pOs2Info2->usri2_script_path, pInfo2->usri2_script_path);
|
|
|
|
pOs2Info2->usri2_auth_flags = (unsigned long)pInfo2->usri2_auth_flags;
|
|
|
|
CopyUW2ANSI(pOs2Info2->usri2_full_name, pInfo2->usri2_full_name);
|
|
CopyUW2ANSI(pOs2Info2->usri2_usr_comment, pInfo2->usri2_usr_comment);
|
|
CopyUW2ANSI(pOs2Info2->usri2_parms, pInfo2->usri2_parms);
|
|
CopyUW2ANSI(pOs2Info2->usri2_workstations, pInfo2->usri2_workstations);
|
|
|
|
pOs2Info2->usri2_last_logon = (long)pInfo2->usri2_last_logon;
|
|
pOs2Info2->usri2_last_logoff = (long)pInfo2->usri2_last_logoff;
|
|
pOs2Info2->usri2_acct_expires = (long)pInfo2->usri2_acct_expires;
|
|
pOs2Info2->usri2_max_storage = (unsigned long)pInfo2->usri2_max_storage;
|
|
pOs2Info2->usri2_units_per_week = (unsigned short)pInfo2->usri2_units_per_week;
|
|
StringLen = strlen(pInfo2->usri2_logon_hours) + 1;
|
|
CurEndOfBuffer -= StringLen;
|
|
pOs2Info2->usri2_logon_hours = (char *)FLATTOFARPTR(CurEndOfBuffer);
|
|
RtlMoveMemory(CurEndOfBuffer, pInfo2->usri2_logon_hours, StringLen);
|
|
pOs2Info2->usri2_bad_pw_count = (unsigned short)pInfo2->usri2_bad_pw_count;
|
|
pOs2Info2->usri2_num_logons = (unsigned short)pInfo2->usri2_num_logons;
|
|
|
|
CopyUW2ANSI(pOs2Info2->usri2_logon_server, pInfo2->usri2_logon_server);
|
|
|
|
pOs2Info2->usri2_country_code = (unsigned short)pInfo2->usri2_country_code;
|
|
pOs2Info2->usri2_code_page = (unsigned short)pInfo2->usri2_code_page;
|
|
|
|
pOs2Info2++;
|
|
}
|
|
else if (sLevel == 10) {
|
|
pInfo10 = (PUSER_INFO_10) BufPtr + i;
|
|
StringLen = sizeof(struct user_info_10) +
|
|
UWstrlen(pInfo10->usri10_comment) + 1 +
|
|
UWstrlen(pInfo10->usri10_usr_comment) + 1 +
|
|
UWstrlen(pInfo10->usri10_full_name) + 1;
|
|
if (StringLen > OutBufSize ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
|
|
OutBufSize -= StringLen;
|
|
UW2ANSIstrncpy(pOs2Info10->usri10_name, pInfo10->usri10_name, UNLEN_LM20);
|
|
pOs2Info10->usri10_name[UNLEN_LM20] = '\0';
|
|
|
|
CopyUW2ANSI(pOs2Info10->usri10_comment, pInfo10->usri10_comment);
|
|
CopyUW2ANSI(pOs2Info10->usri10_usr_comment, pInfo10->usri10_usr_comment);
|
|
CopyUW2ANSI(pOs2Info10->usri10_full_name, pInfo10->usri10_full_name);
|
|
|
|
pOs2Info10++;
|
|
}
|
|
#if 0
|
|
else if (sLevel == 11) {
|
|
pInfo11 = (PUSER_INFO_11) BufPtr + i;
|
|
StringLen = sizeof(struct user_info_11) +
|
|
UWstrlen(pInfo11->usri11_comment) + 1 +
|
|
UWstrlen(pInfo11->usri11_usr_comment) + 1 +
|
|
UWstrlen(pInfo11->usri11_full_name) + 1 +
|
|
UWstrlen(pInfo11->usri11_home_dir) + 1 +
|
|
UWstrlen(pInfo11->usri11_parms) + 1 +
|
|
UWstrlen(pInfo11->usri11_logon_server) + 1 +
|
|
UWstrlen(pInfo11->usri11_workstations) + 1 +
|
|
strlen(pInfo11->usri11_logon_hours) + 1;
|
|
if (StringLen > OutBufSize ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
|
|
OutBufSize -= StringLen;
|
|
UW2ANSIstrncpy(pOs2Info11->usri11_name, pInfo11->usri11_name, UNLEN_LM20);
|
|
pOs2Info11->usri11_name[UNLEN_LM20] = '\0';
|
|
|
|
CopyUW2ANSI(pOs2Info11->usri11_comment, pInfo11->usri11_comment);
|
|
CopyUW2ANSI(pOs2Info11->usri11_usr_comment, pInfo11->usri11_usr_comment);
|
|
CopyUW2ANSI(pOs2Info11->usri11_full_name, pInfo11->usri11_full_name);
|
|
|
|
pOs2Info11->usri11_priv = (unsigned short)pInfo11->usri11_priv;
|
|
pOs2Info11->usri11_auth_flags = (unsigned long)pInfo11->usri11_auth_flags;
|
|
pOs2Info11->usri11_password_age = (long)pInfo11->usri11_password_age;
|
|
|
|
CopyUW2ANSI(pOs2Info11->usri11_home_dir, pInfo11->usri11_home_dir);
|
|
CopyUW2ANSI(pOs2Info11->usri11_parms, pInfo11->usri11_parms);
|
|
|
|
pOs2Info11->usri11_last_logon = (long)pInfo11->usri11_last_logon;
|
|
pOs2Info11->usri11_last_logoff = (long)pInfo11->usri11_last_logoff;
|
|
pOs2Info11->usri11_bad_pw_count = (unsigned short)pInfo11->usri11_bad_pw_count;
|
|
pOs2Info11->usri11_num_logons = (unsigned short)pInfo11->usri11_num_logons;
|
|
|
|
CopyUW2ANSI(pOs2Info11->usri11_logon_server, pInfo11->usri11_logon_server);
|
|
|
|
pOs2Info11->usri11_country_code = (unsigned short)pInfo11->usri11_country_code;
|
|
|
|
CopyUW2ANSI(pOs2Info11->usri11_workstations, pInfo11->usri11_workstations);
|
|
|
|
pOs2Info11->usri11_max_storage = (unsigned long)pInfo11->usri11_max_storage;
|
|
pOs2Info11->usri11_units_per_week = (unsigned short)pInfo11->usri11_units_per_week;
|
|
|
|
StringLen = strlen(pInfo11->usri11_logon_hours) + 1;
|
|
CurEndOfBuffer -= StringLen;
|
|
pOs2Info11->usri11_logon_hours = (char *)FLATTOFARPTR(CurEndOfBuffer);
|
|
RtlMoveMemory(CurEndOfBuffer, pInfo11->usri11_logon_hours, StringLen);
|
|
|
|
pOs2Info11->usri11_code_page = (unsigned short)pInfo11->usri11_code_page;
|
|
|
|
pOs2Info11++;
|
|
}
|
|
#endif
|
|
(*pcEntriesRead)++;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16WkstaGetInfo(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
LPBYTE BufPtr1;
|
|
LPBYTE BufPtr2;
|
|
NET_API_STATUS rc;
|
|
PWKSTA_INFO_101 pInfo101;
|
|
PWKSTA_USER_INFO_1 pInfo1;
|
|
struct wksta_info_0 *pOs2Info0;
|
|
struct wksta_info_1 *pOs2Info1;
|
|
struct wksta_info_10 *pOs2Info10;
|
|
PCHAR pStrings;
|
|
WCHAR LanRoot[CCHMAXPATH];
|
|
PCHAR pEndOfBuffer;
|
|
ULONG StringLen;
|
|
ULONG TotalStringLen;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForWrite(pcbTotalAvail,sizeof(*pcbTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1) && (sLevel != 10)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
rc = NetWkstaGetInfo(Server, 101L, &BufPtr1);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
rc = NetWkstaUserGetInfo(NULL, 1L, &BufPtr2);
|
|
|
|
if (rc != NO_ERROR) {
|
|
NetApiBufferFree(BufPtr1);
|
|
return(rc);
|
|
}
|
|
|
|
RtlZeroMemory(pbBuffer, cbBuffer);
|
|
pEndOfBuffer = pbBuffer + cbBuffer;
|
|
pInfo101 = (PWKSTA_INFO_101) BufPtr1;
|
|
pInfo1 = (PWKSTA_USER_INFO_1) BufPtr2;
|
|
|
|
if (sLevel == 0) {
|
|
pOs2Info0 = (struct wksta_info_0 *)pbBuffer;
|
|
|
|
//
|
|
// note about wkix_root - NT returns an empty field.
|
|
// We should return system directory
|
|
// in case of lacal machine, and NULL
|
|
// in case of remote call.
|
|
//
|
|
if ((pszServer == NULL) || (*pszServer == (CHAR) NULL)) {
|
|
StringLen = GetSystemDirectoryW(LanRoot, sizeof(LanRoot)) + 1;
|
|
LanRoot[StringLen] = UNICODE_NULL;
|
|
}
|
|
else {
|
|
StringLen = 1;
|
|
LanRoot[0] = UNICODE_NULL;
|
|
}
|
|
TotalStringLen = UTstrlen(LanRoot) + 1 +
|
|
UTstrlen(pInfo101->wki101_computername) + 1 +
|
|
UTstrlen(pInfo101->wki101_langroup) + 1 +
|
|
UTstrlen(pInfo1->wkui1_username) + 1 +
|
|
UTstrlen(pInfo1->wkui1_logon_server) + 1 + 2;
|
|
*pcbTotalAvail = (USHORT)(sizeof(struct wksta_info_0) + TotalStringLen);
|
|
pStrings = (PCHAR)(pOs2Info0 + 1);
|
|
if (pStrings + TotalStringLen > pEndOfBuffer) {
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UT2ANSIstrcpy(pStrings, LanRoot);
|
|
pOs2Info0->wki0_root = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo101->wki101_computername) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo101->wki101_computername);
|
|
pOs2Info0->wki0_computername = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo101->wki101_langroup) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo101->wki101_langroup);
|
|
pOs2Info0->wki0_langroup = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
pOs2Info0->wki0_ver_major = (unsigned char)pInfo101->wki101_ver_major;
|
|
pOs2Info0->wki0_ver_minor = (unsigned char)pInfo101->wki101_ver_minor;
|
|
|
|
StringLen = UTstrlen(pInfo1->wkui1_username) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo1->wkui1_username);
|
|
pOs2Info0->wki0_username = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
strcpy(pStrings, "\\\\");
|
|
StringLen = UTstrlen(pInfo1->wkui1_logon_server) + 1 + 2;
|
|
UT2ANSIstrcpy(pStrings + 2, pInfo1->wkui1_logon_server);
|
|
pOs2Info0->wki0_logon_server = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
}
|
|
else if (sLevel == 1) {
|
|
pOs2Info1 = (struct wksta_info_1 *)pbBuffer;
|
|
|
|
//
|
|
// note about wkix_root - NT returns an empty field.
|
|
// We should return system directory
|
|
// in case of lacal machine, and NULL
|
|
// in case of remote call.
|
|
//
|
|
if ((pszServer == NULL) || (*pszServer == (CHAR) NULL)) {
|
|
StringLen = GetSystemDirectoryW(LanRoot, sizeof(LanRoot)) + 1;
|
|
LanRoot[StringLen] = UNICODE_NULL;
|
|
}
|
|
else {
|
|
StringLen = 1;
|
|
LanRoot[0] = UNICODE_NULL;
|
|
}
|
|
TotalStringLen = UTstrlen(LanRoot) + 1 +
|
|
UTstrlen(pInfo101->wki101_computername) + 1 +
|
|
UTstrlen(pInfo101->wki101_langroup) + 1 +
|
|
UTstrlen(pInfo1->wkui1_username) + 1 +
|
|
UTstrlen(pInfo1->wkui1_logon_server) + 1 + 2 +
|
|
UTstrlen(pInfo1->wkui1_logon_domain) + 1 +
|
|
UTstrlen(pInfo1->wkui1_oth_domains) + 1;
|
|
*pcbTotalAvail = (USHORT)(sizeof(struct wksta_info_1) + TotalStringLen);
|
|
pStrings = (PCHAR)(pOs2Info1 + 1);
|
|
if (pStrings + TotalStringLen > pEndOfBuffer) {
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UT2ANSIstrcpy(pStrings, LanRoot);
|
|
pOs2Info1->wki1_root = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo101->wki101_computername) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo101->wki101_computername);
|
|
pOs2Info1->wki1_computername = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo101->wki101_langroup) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo101->wki101_langroup);
|
|
pOs2Info1->wki1_langroup = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
pOs2Info1->wki1_ver_major = (unsigned char)pInfo101->wki101_ver_major;
|
|
pOs2Info1->wki1_ver_minor = (unsigned char)pInfo101->wki101_ver_minor;
|
|
|
|
StringLen = UTstrlen(pInfo1->wkui1_username) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo1->wkui1_username);
|
|
pOs2Info1->wki1_username = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
strcpy(pStrings, "\\\\");
|
|
StringLen = UTstrlen(pInfo1->wkui1_logon_server) + 1 + 2;
|
|
UT2ANSIstrcpy(pStrings + 2, pInfo1->wkui1_logon_server);
|
|
pOs2Info1->wki1_logon_server = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo1->wkui1_logon_domain) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo1->wkui1_logon_domain);
|
|
pOs2Info1->wki1_logon_domain = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo1->wkui1_oth_domains) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo1->wkui1_oth_domains);
|
|
pOs2Info1->wki1_oth_domains = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
}
|
|
else if (sLevel == 10) {
|
|
pOs2Info10 = (struct wksta_info_10 *)pbBuffer;
|
|
TotalStringLen = UTstrlen(pInfo101->wki101_computername) + 1 +
|
|
UTstrlen(pInfo1->wkui1_username) + 1 +
|
|
UTstrlen(pInfo101->wki101_langroup) + 1 +
|
|
UTstrlen(pInfo1->wkui1_logon_domain) + 1 +
|
|
UTstrlen(pInfo1->wkui1_oth_domains) + 1;
|
|
*pcbTotalAvail = (USHORT)(sizeof(struct wksta_info_10) + TotalStringLen);
|
|
pStrings = (PCHAR)(pOs2Info10 + 1);
|
|
if (pStrings + TotalStringLen > pEndOfBuffer) {
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
StringLen = UTstrlen(pInfo101->wki101_computername) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo101->wki101_computername);
|
|
pOs2Info10->wki10_computername = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo1->wkui1_username) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo1->wkui1_username);
|
|
pOs2Info10->wki10_username = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo101->wki101_langroup) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo101->wki101_langroup);
|
|
pOs2Info10->wki10_langroup = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
pOs2Info10->wki10_ver_major = (unsigned char)pInfo101->wki101_ver_major;
|
|
pOs2Info10->wki10_ver_minor = (unsigned char)pInfo101->wki101_ver_minor;
|
|
|
|
StringLen = UTstrlen(pInfo1->wkui1_logon_domain) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo1->wkui1_logon_domain);
|
|
pOs2Info10->wki10_logon_domain = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
|
|
StringLen = UTstrlen(pInfo1->wkui1_oth_domains) + 1;
|
|
UT2ANSIstrcpy(pStrings, pInfo1->wkui1_oth_domains);
|
|
pOs2Info10->wki10_oth_domains = (char *)FLATTOFARPTR(pStrings);
|
|
pStrings += StringLen;
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr1);
|
|
NetApiBufferFree(BufPtr2);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16AccessAdd(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
IN PCHAR pbBuffer,
|
|
IN ULONG cbBuffer
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
PCHAR Buffer;
|
|
PCHAR ResourceName;
|
|
LPTSTR pStrings;
|
|
ULONG StringLen;
|
|
PACCESS_INFO_1 pInfo1;
|
|
PACCESS_LIST pInfo;
|
|
struct access_info_1 *pOs2Info1;
|
|
struct access_list *pOs2Info;
|
|
int i;
|
|
NET_API_STATUS rc;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForRead(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sLevel != 1) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
Buffer = (PCHAR) RtlAllocateHeap(Od2Heap, 0, LARGE_BUFFER_SIZE);
|
|
|
|
if (Buffer == NULL) {
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
pOs2Info1 = (struct access_info_1 *) pbBuffer;
|
|
pOs2Info = (struct access_list *) (pOs2Info1 + 1);
|
|
pInfo1 = (PACCESS_INFO_1) Buffer;
|
|
pInfo = (PACCESS_LIST) (pInfo1 + 1);
|
|
pStrings = (LPTSTR)(pInfo + (pOs2Info1->acc1_count * sizeof(ACCESS_LIST)));
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
ResourceName = FARPTRTOFLAT(pOs2Info1->acc1_resource_name);
|
|
pInfo1->acc1_resource_name = pStrings;
|
|
StringLen = strlen(ResourceName) + 1;
|
|
ANSI2UTstrcpy(pStrings, ResourceName);
|
|
pStrings += StringLen;
|
|
|
|
pInfo1->acc1_attr = pOs2Info1->acc1_attr;
|
|
pInfo1->acc1_count = pOs2Info1->acc1_count;
|
|
|
|
for (i = 0; i < pOs2Info1->acc1_count; i++) {
|
|
pInfo->acl_access = pOs2Info->acl_access;
|
|
pInfo->acl_ugname = pStrings;
|
|
ANSI2UTstrcpy(pStrings, pOs2Info->acl_ugname);
|
|
pStrings += UNLEN_LM20+1;
|
|
pInfo++;
|
|
pOs2Info++;
|
|
}
|
|
|
|
rc = NetAccessAdd(Server, sLevel, Buffer, NULL);
|
|
|
|
RtlFreeHeap(Od2Heap, 0, Buffer);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16AccessSetInfo(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszResource,
|
|
IN LONG sLevel,
|
|
IN PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
IN LONG sParmNum
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR Resource[NNLEN];
|
|
PCHAR Buffer = NULL;
|
|
NET_API_STATUS rc;
|
|
ACCESS_INFO_1002 AccessInfo1002;
|
|
PCHAR ResourceName;
|
|
LPTSTR pStrings;
|
|
ULONG StringLen;
|
|
PACCESS_INFO_1 pInfo1;
|
|
PACCESS_LIST pInfo;
|
|
struct access_info_1 *pOs2Info1;
|
|
struct access_list *pOs2Info;
|
|
int i;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszResource);
|
|
Od2ProbeForRead(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sLevel != 1) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(Resource, pszResource, NNLEN);
|
|
|
|
if (sParmNum == ACCESS_ATTR_PARMNUM) {
|
|
AccessInfo1002.acc1002_attr = *(PSHORT) pbBuffer;
|
|
rc = NetAccessSetInfo(Server, Resource, (ULONG) 1002, (PCHAR) &AccessInfo1002, NULL);
|
|
} else {
|
|
|
|
Buffer = (PCHAR) RtlAllocateHeap(Od2Heap, 0, LARGE_BUFFER_SIZE);
|
|
|
|
if (Buffer == NULL) {
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
pOs2Info1 = (struct access_info_1 *) pbBuffer;
|
|
pOs2Info = (struct access_list *) (pOs2Info1 + 1);
|
|
pInfo1 = (PACCESS_INFO_1) Buffer;
|
|
pInfo = (PACCESS_LIST) (pInfo1 + 1);
|
|
pStrings = (LPTSTR)(pInfo + (pOs2Info1->acc1_count * sizeof(ACCESS_LIST)));
|
|
|
|
ResourceName = FARPTRTOFLAT(pOs2Info1->acc1_resource_name);
|
|
pInfo1->acc1_resource_name = pStrings;
|
|
StringLen = strlen(ResourceName) + 1;
|
|
ANSI2UTstrcpy(pStrings, ResourceName);
|
|
pStrings += StringLen;
|
|
|
|
pInfo1->acc1_attr = pOs2Info1->acc1_attr;
|
|
pInfo1->acc1_count = pOs2Info1->acc1_count;
|
|
|
|
for (i = 0; i < pOs2Info1->acc1_count; i++) {
|
|
pInfo->acl_access = pOs2Info->acl_access;
|
|
pInfo->acl_ugname = pStrings;
|
|
ANSI2UTstrcpy(pStrings, pOs2Info->acl_ugname);
|
|
pStrings += UNLEN_LM20+1;
|
|
pInfo++;
|
|
pOs2Info++;
|
|
}
|
|
rc = NetAccessSetInfo(Server, Resource, sLevel, Buffer, NULL);
|
|
|
|
RtlFreeHeap(Od2Heap, 0, Buffer);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16AccessGetInfo(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszResource,
|
|
IN LONG sLevel,
|
|
OUT PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
ANSI_STRING Str_MB;
|
|
UNICODE_STRING Str_U;
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
APIRET RetCode;
|
|
PACCESS_INFO_0 pInfo0;
|
|
PACCESS_INFO_1 pInfo1;
|
|
PACCESS_LIST pInfo;
|
|
struct access_info_0 *pOs2Info0;
|
|
struct access_info_1 *pOs2Info1;
|
|
struct access_list *pOs2Info;
|
|
ULONG strucsize;
|
|
ULONG Length;
|
|
ULONG FullLength;
|
|
ULONG StringLen;
|
|
ULONG AclsThatFit;
|
|
ULONG Count;
|
|
PCHAR pScratch;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszResource);
|
|
Od2ProbeForWrite(pcbTotalAvail,sizeof(*pcbTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16AccessGetInfo: Invalid level = %d\n", sLevel));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_LEVEL);
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
//
|
|
// Since Resource can be a very long string (up to PATHLEN), we allocate
|
|
// space for it on the heap instead of the stack, which might be too short
|
|
//
|
|
|
|
if (pszResource != NULL) {
|
|
|
|
Or2InitMBString(&Str_MB, pszResource);
|
|
|
|
if ((RetCode = Or2MBStringToUnicodeString(&Str_U, &Str_MB, TRUE)) != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16AccessGetInfo: Unicode converstion of Resource failed, RetCode = %x\n", RetCode));
|
|
}
|
|
#endif
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
Str_U.Buffer[Str_U.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
} else {
|
|
|
|
Str_U.Buffer = NULL;
|
|
}
|
|
|
|
rc = NetAccessGetInfo(Server, (LPTSTR) Str_U.Buffer, sLevel, &BufPtr);
|
|
|
|
if (Str_U.Buffer != NULL) {
|
|
RtlFreeUnicodeString(&Str_U);
|
|
}
|
|
|
|
if (rc != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16AccessGetInfo: System function returned %lx\n", rc));
|
|
}
|
|
#endif
|
|
return((APIRET)rc);
|
|
}
|
|
|
|
if (sLevel == 0) {
|
|
|
|
strucsize = sizeof(struct access_info_0);
|
|
pInfo0 = (PACCESS_INFO_0) BufPtr;
|
|
|
|
RtlInitUnicodeString(&Str_U, pInfo0->acc0_resource_name);
|
|
|
|
if (Str_U.Buffer == NULL) {
|
|
|
|
StringLen = 0;
|
|
|
|
} else {
|
|
|
|
if ((RetCode = Or2UnicodeStringToMBString(&Str_MB, &Str_U, TRUE)) != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16AccessGetInfo: Unicode converstion of returned resource name failed, RetCode = %x\n", RetCode));
|
|
}
|
|
#endif
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
StringLen = Str_MB.Length + 1;
|
|
}
|
|
|
|
*pcbTotalAvail = (USHORT) (strucsize + StringLen);
|
|
|
|
if (cbBuffer < strucsize + StringLen) {
|
|
if (StringLen != 0) {
|
|
Or2FreeMBString(&Str_MB);
|
|
}
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
pOs2Info0 = (struct access_info_0 *) pbBuffer;
|
|
|
|
if (StringLen) {
|
|
|
|
pScratch = (PCHAR) (pOs2Info0 + 1);
|
|
pOs2Info0->acc0_resource_name = (PVOID) FLATTOFARPTR(pScratch);
|
|
RtlMoveMemory(pScratch, Str_MB.Buffer, StringLen);
|
|
Or2FreeMBString(&Str_MB);
|
|
|
|
} else {
|
|
|
|
pOs2Info0->acc0_resource_name = NULL;
|
|
}
|
|
|
|
} else { // sLevel == 1
|
|
|
|
strucsize = sizeof(struct access_info_1);
|
|
pInfo1 = (PACCESS_INFO_1) BufPtr;
|
|
|
|
RtlInitUnicodeString(&Str_U, pInfo1->acc1_resource_name);
|
|
|
|
if (Str_U.Buffer == NULL) {
|
|
|
|
StringLen = 0;
|
|
|
|
} else {
|
|
|
|
if ((RetCode = Or2UnicodeStringToMBString(&Str_MB, &Str_U, TRUE)) != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16AccessGetInfo: Unicode converstion of returned resource name failed, RetCode = %x\n", RetCode));
|
|
}
|
|
#endif
|
|
NetApiBufferFree(BufPtr);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
StringLen = Str_MB.Length + 1;
|
|
}
|
|
|
|
AclsThatFit = (ULONG) pInfo1->acc1_count;
|
|
FullLength = Length = AclsThatFit * sizeof(struct access_list);
|
|
|
|
*pcbTotalAvail = (USHORT) (strucsize + FullLength + StringLen);
|
|
|
|
if (cbBuffer < strucsize + StringLen) {
|
|
if (StringLen != 0) {
|
|
Or2FreeMBString(&Str_MB);
|
|
}
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
if (cbBuffer < strucsize + StringLen + Length) {
|
|
|
|
//
|
|
// Cut the info down to size...
|
|
//
|
|
|
|
AclsThatFit = (cbBuffer - strucsize - StringLen) / sizeof(struct access_list);
|
|
|
|
Length = AclsThatFit * sizeof(struct access_list);
|
|
|
|
rc = ERROR_MORE_DATA;
|
|
}
|
|
|
|
pOs2Info1 = (struct access_info_1 *) pbBuffer;
|
|
|
|
if (StringLen) {
|
|
|
|
pScratch = pbBuffer + strucsize + Length;
|
|
pOs2Info1->acc1_resource_name = (PVOID) FLATTOFARPTR(pScratch);
|
|
RtlMoveMemory(pScratch, Str_MB.Buffer, StringLen);
|
|
Or2FreeMBString(&Str_MB);
|
|
|
|
} else {
|
|
|
|
pOs2Info1->acc1_resource_name = NULL;
|
|
}
|
|
|
|
pOs2Info1->acc1_attr = (SHORT) pInfo1->acc1_attr;
|
|
pOs2Info1->acc1_count = (SHORT) AclsThatFit;
|
|
|
|
//
|
|
// Fill in the ACL structures
|
|
//
|
|
|
|
pInfo = (PACCESS_LIST) (pInfo1 + 1);
|
|
pOs2Info = (struct access_list *) (pOs2Info1 + 1);
|
|
|
|
for (Count = 0; Count < AclsThatFit; Count++) {
|
|
|
|
pOs2Info[Count].acl_access = (SHORT) pInfo[Count].acl_access;
|
|
UT2ANSIstrncpy(pOs2Info[Count].acl_ugname, pInfo[Count].acl_ugname, LM20_UNLEN);
|
|
pOs2Info[Count].acl_ugname[LM20_UNLEN] = '\0';
|
|
}
|
|
|
|
}
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
return((APIRET)rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16AccessDel(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszResource
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR Resource[NNLEN];
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszResource);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(Resource, pszResource, NNLEN);
|
|
|
|
return (NetAccessDel(Server, Resource));
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ShareAdd(
|
|
IN PCHAR pszServer,
|
|
IN LONG sLevel,
|
|
IN PCHAR pbBuffer,
|
|
IN ULONG cbBuffer
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
PCHAR Buffer;
|
|
NET_API_STATUS rc;
|
|
LPTSTR pStrings;
|
|
PSHARE_INFO_2 pInfo2;
|
|
struct share_info_2 *pOs2Info2;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
Od2ProbeForRead(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sLevel != 2) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
Buffer = (PCHAR) RtlAllocateHeap(Od2Heap, 0, SMALL_BUFFER_SIZE);
|
|
|
|
if (Buffer == NULL) {
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
pOs2Info2 = (struct share_info_2 *) pbBuffer;
|
|
pInfo2 = (PSHARE_INFO_2) Buffer;
|
|
pStrings = (LPTSTR) (pInfo2 + 1);
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
|
|
pInfo2->shi2_netname = pStrings;
|
|
ANSI2UTstrcpy(pStrings, pOs2Info2->shi2_netname);
|
|
pStrings += strlen(pOs2Info2->shi2_netname) + 1;
|
|
|
|
pInfo2->shi2_remark = pStrings;
|
|
ANSI2UTstrcpy(pStrings, FARPTRTOFLAT(pOs2Info2->shi2_remark));
|
|
pStrings += strlen(FARPTRTOFLAT(pOs2Info2->shi2_remark)) + 1;
|
|
|
|
pInfo2->shi2_path = pStrings;
|
|
ANSI2UTstrcpy(pStrings, FARPTRTOFLAT(pOs2Info2->shi2_path));
|
|
pStrings += strlen(FARPTRTOFLAT(pOs2Info2->shi2_path)) + 1;
|
|
|
|
pInfo2->shi2_passwd = pStrings;
|
|
ANSI2UTstrcpy(pStrings, pOs2Info2->shi2_passwd);
|
|
pStrings += strlen(pOs2Info2->shi2_passwd) + 1;
|
|
|
|
pInfo2->shi2_type = pOs2Info2->shi2_type;
|
|
pInfo2->shi2_permissions = pOs2Info2->shi2_permissions;
|
|
pInfo2->shi2_max_uses = pOs2Info2->shi2_max_uses;
|
|
pInfo2->shi2_current_uses = pOs2Info2->shi2_current_uses;
|
|
|
|
rc = NetShareAdd(Server, sLevel, Buffer, NULL);
|
|
|
|
RtlFreeHeap(Od2Heap, 0, Buffer);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16ShareDel(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszNetName,
|
|
IN ULONG usReserved
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR NetName[NNLEN];
|
|
|
|
UNREFERENCED_PARAMETER(usReserved);
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszNetName);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(NetName, pszNetName, NNLEN);
|
|
|
|
return (NetShareDel(Server, NetName, 0L));
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16UserGetInfo(
|
|
IN PCHAR pszServer,
|
|
IN PCHAR pszUserName,
|
|
IN LONG sLevel,
|
|
IN PCHAR pbBuffer,
|
|
IN ULONG cbBuffer,
|
|
OUT PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
WCHAR Server[UNCLEN];
|
|
WCHAR UserName[UNLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PUSER_INFO_0 pInfo0;
|
|
PUSER_INFO_1 pInfo1;
|
|
PUSER_INFO_2 pInfo2;
|
|
PUSER_INFO_10 pInfo10;
|
|
PUSER_INFO_11 pInfo11;
|
|
struct user_info_0 *pOs2Info0;
|
|
struct user_info_1 *pOs2Info1;
|
|
struct user_info_2 *pOs2Info2;
|
|
struct user_info_10 *pOs2Info10;
|
|
struct user_info_11 *pOs2Info11;
|
|
PCHAR CurEndOfBuffer;
|
|
ULONG StringLen;
|
|
ULONG TotalStringLen;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszUserName);
|
|
Od2ProbeForWrite(pcbTotalAvail,sizeof(*pcbTotalAvail),1);
|
|
Od2ProbeForWrite(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((sLevel != 0) && (sLevel != 1) && (sLevel != 2) &&
|
|
(sLevel != 10) && (sLevel != 11)) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
ANSI2UWstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UWstrncpy(UserName, pszUserName, UNLEN);
|
|
|
|
rc = NetUserGetInfo(Server, UserName, sLevel, &BufPtr);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
CurEndOfBuffer = pbBuffer + cbBuffer;
|
|
|
|
if (sLevel == 0) {
|
|
pInfo0 = (PUSER_INFO_0) BufPtr;
|
|
pOs2Info0 = (struct user_info_0 *)pbBuffer;
|
|
*pcbTotalAvail = (USHORT)sizeof(struct user_info_0);
|
|
if ((ULONG)sizeof(struct user_info_0) > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
UW2ANSIstrncpy(pOs2Info0->usri0_name, pInfo0->usri0_name, UNLEN_LM20);
|
|
pOs2Info0->usri0_name[UNLEN_LM20] = '\0';
|
|
}
|
|
else if (sLevel == 1) {
|
|
pInfo1 = (PUSER_INFO_1) BufPtr;
|
|
pOs2Info1 = (struct user_info_1 *)pbBuffer;
|
|
TotalStringLen = sizeof(struct user_info_1) +
|
|
UWstrlen(pInfo1->usri1_home_dir) + 1 +
|
|
UWstrlen(pInfo1->usri1_comment) + 1 +
|
|
UWstrlen(pInfo1->usri1_script_path) + 1;
|
|
*pcbTotalAvail = (USHORT)TotalStringLen;
|
|
if (TotalStringLen > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UW2ANSIstrncpy(pOs2Info1->usri1_name, pInfo1->usri1_name, UNLEN_LM20);
|
|
pOs2Info1->usri1_name[UNLEN_LM20] = '\0';
|
|
|
|
UW2ANSIstrncpy(pOs2Info1->usri1_password, pInfo1->usri1_password, ENCRYPTED_PWLEN_LM20);
|
|
pOs2Info1->usri1_password[ENCRYPTED_PWLEN_LM20] = '\0';
|
|
|
|
CopyUW2ANSI(pOs2Info1->usri1_home_dir, pInfo1->usri1_home_dir);
|
|
CopyUW2ANSI(pOs2Info1->usri1_comment, pInfo1->usri1_comment);
|
|
CopyUW2ANSI(pOs2Info1->usri1_script_path, pInfo1->usri1_script_path);
|
|
|
|
pOs2Info1->usri1_password_age = (long)pInfo1->usri1_password_age;
|
|
pOs2Info1->usri1_priv = (unsigned short)pInfo1->usri1_priv;
|
|
pOs2Info1->usri1_flags = (unsigned short)pInfo1->usri1_flags;
|
|
}
|
|
else if (sLevel == 2) {
|
|
pInfo2 = (PUSER_INFO_2) BufPtr;
|
|
pOs2Info2 = (struct user_info_2 *)pbBuffer;
|
|
TotalStringLen = sizeof(struct user_info_2) +
|
|
UWstrlen(pInfo2->usri2_home_dir) + 1 +
|
|
UWstrlen(pInfo2->usri2_comment) + 1 +
|
|
UWstrlen(pInfo2->usri2_script_path) + 1 +
|
|
UWstrlen(pInfo2->usri2_full_name) + 1 +
|
|
UWstrlen(pInfo2->usri2_usr_comment) + 1 +
|
|
UWstrlen(pInfo2->usri2_parms) + 1 +
|
|
UWstrlen(pInfo2->usri2_workstations) + 1 +
|
|
strlen(pInfo2->usri2_logon_hours) +
|
|
UWstrlen(pInfo2->usri2_logon_server) + 1;
|
|
*pcbTotalAvail = (USHORT)TotalStringLen;
|
|
if (TotalStringLen > cbBuffer) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UW2ANSIstrncpy(pOs2Info2->usri2_name, pInfo2->usri2_name, UNLEN_LM20);
|
|
pOs2Info2->usri2_name[UNLEN_LM20] = '\0';
|
|
|
|
UW2ANSIstrncpy(pOs2Info2->usri2_password, pInfo2->usri2_password, ENCRYPTED_PWLEN_LM20);
|
|
pOs2Info2->usri2_password[ENCRYPTED_PWLEN_LM20] = '\0';
|
|
|
|
CopyUW2ANSI(pOs2Info2->usri2_home_dir, pInfo2->usri2_home_dir);
|
|
CopyUW2ANSI(pOs2Info2->usri2_comment, pInfo2->usri2_comment);
|
|
CopyUW2ANSI(pOs2Info2->usri2_script_path, pInfo2->usri2_script_path);
|
|
CopyUW2ANSI(pOs2Info2->usri2_full_name, pInfo2->usri2_full_name);
|
|
CopyUW2ANSI(pOs2Info2->usri2_usr_comment, pInfo2->usri2_usr_comment);
|
|
CopyUW2ANSI(pOs2Info2->usri2_parms, pInfo2->usri2_parms);
|
|
CopyUW2ANSI(pOs2Info2->usri2_workstations, pInfo2->usri2_workstations);
|
|
CopyUW2ANSI(pOs2Info2->usri2_logon_server, pInfo2->usri2_logon_server);
|
|
StringLen = strlen(pInfo2->usri2_logon_hours) + 1;
|
|
CurEndOfBuffer -= StringLen;
|
|
pOs2Info2->usri2_logon_hours = (char *)FLATTOFARPTR(CurEndOfBuffer);
|
|
RtlMoveMemory(CurEndOfBuffer, pInfo2->usri2_logon_hours, StringLen);
|
|
|
|
pOs2Info2->usri2_password_age = (long)pInfo2->usri2_password_age;
|
|
pOs2Info2->usri2_priv = (unsigned short)pInfo2->usri2_priv;
|
|
pOs2Info2->usri2_flags = (unsigned short)pInfo2->usri2_flags;
|
|
pOs2Info2->usri2_auth_flags = (unsigned long)pInfo2->usri2_auth_flags;
|
|
pOs2Info2->usri2_last_logon = (long)pInfo2->usri2_last_logon;
|
|
pOs2Info2->usri2_last_logoff = (long)pInfo2->usri2_last_logoff;
|
|
pOs2Info2->usri2_acct_expires = (long)pInfo2->usri2_acct_expires;
|
|
pOs2Info2->usri2_max_storage = (unsigned long)pInfo2->usri2_max_storage;
|
|
pOs2Info2->usri2_units_per_week = (unsigned short)pInfo2->usri2_units_per_week;
|
|
pOs2Info2->usri2_bad_pw_count = (unsigned short)pInfo2->usri2_bad_pw_count;
|
|
pOs2Info2->usri2_num_logons = (unsigned short)pInfo2->usri2_num_logons;
|
|
pOs2Info2->usri2_country_code = (unsigned short)pInfo2->usri2_country_code;
|
|
pOs2Info2->usri2_code_page = (unsigned short)pInfo2->usri2_code_page;
|
|
}
|
|
else if (sLevel == 10) {
|
|
pInfo10 = (PUSER_INFO_10) BufPtr;
|
|
pOs2Info10 = (struct user_info_10 *)pbBuffer;
|
|
TotalStringLen = sizeof(struct user_info_10) +
|
|
UWstrlen(pInfo10->usri10_comment) + 1 +
|
|
UWstrlen(pInfo10->usri10_usr_comment) + 1 +
|
|
UWstrlen(pInfo10->usri10_full_name) + 1;
|
|
*pcbTotalAvail = (USHORT)TotalStringLen;
|
|
if (TotalStringLen > cbBuffer ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UW2ANSIstrncpy(pOs2Info10->usri10_name, pInfo10->usri10_name, UNLEN_LM20);
|
|
pOs2Info10->usri10_name[UNLEN_LM20] = '\0';
|
|
|
|
CopyUW2ANSI(pOs2Info10->usri10_comment, pInfo10->usri10_comment);
|
|
CopyUW2ANSI(pOs2Info10->usri10_usr_comment, pInfo10->usri10_usr_comment);
|
|
CopyUW2ANSI(pOs2Info10->usri10_full_name, pInfo10->usri10_full_name);
|
|
}
|
|
else if (sLevel == 11) {
|
|
pInfo11 = (PUSER_INFO_11) BufPtr;
|
|
pOs2Info11 = (struct user_info_11 *)pbBuffer;
|
|
TotalStringLen = sizeof(struct user_info_11) +
|
|
UWstrlen(pInfo11->usri11_comment) + 1 +
|
|
UWstrlen(pInfo11->usri11_usr_comment) + 1 +
|
|
UWstrlen(pInfo11->usri11_full_name) + 1 +
|
|
UWstrlen(pInfo11->usri11_home_dir) + 1 +
|
|
UWstrlen(pInfo11->usri11_parms) + 1 +
|
|
UWstrlen(pInfo11->usri11_logon_server) + 1 +
|
|
UWstrlen(pInfo11->usri11_workstations) + 1 +
|
|
strlen(pInfo11->usri11_logon_hours);
|
|
*pcbTotalAvail = (USHORT)TotalStringLen;
|
|
if (TotalStringLen > cbBuffer ) {
|
|
NetApiBufferFree(BufPtr);
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
UW2ANSIstrncpy(pOs2Info11->usri11_name, pInfo11->usri11_name, UNLEN_LM20);
|
|
pOs2Info11->usri11_name[UNLEN_LM20] = '\0';
|
|
|
|
CopyUW2ANSI(pOs2Info11->usri11_comment, pInfo11->usri11_comment);
|
|
CopyUW2ANSI(pOs2Info11->usri11_usr_comment, pInfo11->usri11_usr_comment);
|
|
CopyUW2ANSI(pOs2Info11->usri11_full_name, pInfo11->usri11_full_name);
|
|
|
|
pOs2Info11->usri11_priv = (unsigned short)pInfo11->usri11_priv;
|
|
pOs2Info11->usri11_auth_flags = (unsigned long)pInfo11->usri11_auth_flags;
|
|
pOs2Info11->usri11_password_age = (long)pInfo11->usri11_password_age;
|
|
|
|
CopyUW2ANSI(pOs2Info11->usri11_home_dir, pInfo11->usri11_home_dir);
|
|
CopyUW2ANSI(pOs2Info11->usri11_parms, pInfo11->usri11_parms);
|
|
|
|
pOs2Info11->usri11_last_logon = (long)pInfo11->usri11_last_logon;
|
|
pOs2Info11->usri11_last_logoff = (long)pInfo11->usri11_last_logoff;
|
|
pOs2Info11->usri11_bad_pw_count = (unsigned short)pInfo11->usri11_bad_pw_count;
|
|
pOs2Info11->usri11_num_logons = (unsigned short)pInfo11->usri11_num_logons;
|
|
|
|
CopyUW2ANSI(pOs2Info11->usri11_logon_server, pInfo11->usri11_logon_server);
|
|
|
|
pOs2Info11->usri11_country_code = (unsigned short)pInfo11->usri11_country_code;
|
|
|
|
CopyUW2ANSI(pOs2Info11->usri11_workstations, pInfo11->usri11_workstations);
|
|
|
|
pOs2Info11->usri11_max_storage = (unsigned long)pInfo11->usri11_max_storage;
|
|
pOs2Info11->usri11_units_per_week = (unsigned short)pInfo11->usri11_units_per_week;
|
|
|
|
StringLen = strlen(pInfo11->usri11_logon_hours) + 1;
|
|
CurEndOfBuffer -= StringLen;
|
|
pOs2Info11->usri11_logon_hours = (char *)FLATTOFARPTR(CurEndOfBuffer);
|
|
RtlMoveMemory(CurEndOfBuffer, pInfo11->usri11_logon_hours, StringLen);
|
|
|
|
pOs2Info11->usri11_code_page = (unsigned short)pInfo11->usri11_code_page;
|
|
}
|
|
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16MessageBufferSend(
|
|
IN PSZ pszServer,
|
|
IN PSZ pszRecipient,
|
|
IN PBYTE pbBuffer,
|
|
IN ULONG cbBuffer
|
|
)
|
|
{
|
|
TCHAR Server[UNCLEN];
|
|
TCHAR Recipient[CNLEN+1];
|
|
ANSI_STRING Tmp_MB;
|
|
UNICODE_STRING Tmp_U;
|
|
APIRET rc;
|
|
|
|
try {
|
|
PROBE_STRING(pszServer);
|
|
PROBE_STRING(pszRecipient);
|
|
Od2ProbeForRead(pbBuffer,cbBuffer,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
ANSI2UTstrncpy(Server, pszServer, UNCLEN);
|
|
ANSI2UTstrncpy(Recipient, pszRecipient, CNLEN+1);
|
|
|
|
//
|
|
// We now need to convert the message buffer
|
|
// itself to unicode...
|
|
//
|
|
|
|
Tmp_MB.Buffer = (PCHAR) pbBuffer;
|
|
Tmp_MB.MaximumLength = Tmp_MB.Length = (USHORT) cbBuffer;
|
|
|
|
rc = Od2MBStringToUnicodeString(
|
|
&Tmp_U,
|
|
&Tmp_MB,
|
|
TRUE);
|
|
|
|
if (rc != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16MessageBufferSend: Failed to convert buffer to unicode, rc = %lx\n", rc));
|
|
}
|
|
#endif
|
|
return(rc);
|
|
}
|
|
|
|
rc = (APIRET) NetMessageBufferSend(Server, Recipient, NULL, (PBYTE) Tmp_U.Buffer, (ULONG) Tmp_U.Length);
|
|
|
|
RtlFreeUnicodeString(&Tmp_U);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//Following is the implementation of the Netbios APIs
|
|
//
|
|
//*****************************************************************************
|
|
|
|
|
|
#if 1
|
|
#if DBG
|
|
// This is a small debug routine to dump a buffer
|
|
static
|
|
VOID
|
|
Od2BufDbgPrint(
|
|
PBYTE p,
|
|
ULONG c
|
|
)
|
|
{
|
|
ULONG i, m;
|
|
|
|
for (i=0; i < c; i++) {
|
|
m = i%16;
|
|
|
|
if (m == 0) {
|
|
KdPrint((" "));
|
|
}
|
|
|
|
KdPrint(("%2.2x ",p[i]));
|
|
|
|
if (m == 15) {
|
|
KdPrint(("\n"));
|
|
}
|
|
}
|
|
|
|
if (m != 15) {
|
|
KdPrint(("\n"));
|
|
}
|
|
}
|
|
|
|
// This is a small debug routine to print an NCB
|
|
static
|
|
VOID
|
|
Od2NcbDbgPrint(
|
|
IN PNCB pNcb,
|
|
IN PNCB pOs2Ncb,
|
|
IN ULONG EntryPoint
|
|
)
|
|
{
|
|
CHAR CallName[NCBNAMSZ+1];
|
|
CHAR Name[NCBNAMSZ+1];
|
|
UCHAR SynchCommand = pNcb->ncb_command & ~ASYNCH;
|
|
UCHAR Asynch = pNcb->ncb_command & ASYNCH;
|
|
|
|
switch (EntryPoint) {
|
|
case 1:
|
|
KdPrint(("BEFORE, User Ncb addr = %lx\n", (ULONG)pOs2Ncb));
|
|
break;
|
|
case 2:
|
|
KdPrint(("AFTER\n"));
|
|
break;
|
|
case 3:
|
|
KdPrint(("POST-END\n"));
|
|
break;
|
|
}
|
|
|
|
memcpy(CallName, pNcb->ncb_callname, NCBNAMSZ);
|
|
CallName[NCBNAMSZ] = '\0';
|
|
memcpy(Name, pNcb->ncb_name, NCBNAMSZ);
|
|
Name[NCBNAMSZ] = '\0';
|
|
KdPrint(("Netbios call frame:\n"));
|
|
KdPrint(("------------------\n"));
|
|
if (EntryPoint != 3) {
|
|
KdPrint(("TID : 0x%lx\n", NtCurrentTeb()->EnvironmentPointer ? Od2CurrentThreadId() : -1));
|
|
}
|
|
KdPrint(("Command: 0x%x\n", pNcb->ncb_command));
|
|
KdPrint(("Retcode: 0x%x\n", pNcb->ncb_retcode));
|
|
KdPrint(("LSN : 0x%x\n", pNcb->ncb_lsn));
|
|
KdPrint(("NUM : 0x%x\n", pNcb->ncb_num));
|
|
KdPrint(("LanaNum: 0x%x\n", pNcb->ncb_lana_num));
|
|
KdPrint(("Length : 0x%x\n", pNcb->ncb_length));
|
|
KdPrint(("Callnam: %s\n", CallName));
|
|
KdPrint(("Name : %s\n", Name));
|
|
if (EntryPoint == 1 && Asynch) {
|
|
KdPrint(("Post : 0x%lx\n", (ULONG)pOs2Ncb->ncb_post));
|
|
}
|
|
|
|
switch (EntryPoint) {
|
|
case 1:
|
|
if (SynchCommand != NCBSEND &&
|
|
SynchCommand != NCBCHAINSEND) {
|
|
return;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (Asynch) {
|
|
return;
|
|
}
|
|
case 3:
|
|
if (SynchCommand != NCBRECV) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
KdPrint(("Buffer : \n"));
|
|
Od2BufDbgPrint((PBYTE) pNcb->ncb_buffer, (ULONG) pNcb->ncb_length);
|
|
if (SynchCommand == NCBCHAINSEND ||
|
|
SynchCommand == NCBCHAINSENDNA) {
|
|
|
|
ULONG l = (ULONG) (*(PUSHORT)pNcb->ncb_callname);
|
|
|
|
KdPrint(("Length2: 0x%lx\n", l));
|
|
KdPrint(("Buffer2: \n"));
|
|
|
|
Od2BufDbgPrint(*(PBYTE *)&pNcb->ncb_callname[2], l);
|
|
|
|
}
|
|
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
// This routine transfers results from a completed internal NCB to the user's NCB
|
|
static
|
|
VOID
|
|
Od2CopyNcbResults(
|
|
OUT PNCB Dest,
|
|
IN PNCB Src,
|
|
IN BOOLEAN Nb2Semantics
|
|
)
|
|
{
|
|
UCHAR SynchCommand = Src->ncb_command & ~ASYNCH;
|
|
|
|
//
|
|
// For Netbios 3.0 just copy the NCB block
|
|
//
|
|
if (!Nb2Semantics) {
|
|
RtlMoveMemory(Dest, Src, sizeof(NCB));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Netbios 2.0
|
|
|
|
Dest->ncb_lsn = Src->ncb_lsn;
|
|
Dest->ncb_num = Src->ncb_num;
|
|
Dest->ncb_length = Src->ncb_length;
|
|
if (SynchCommand != NCBCHAINSEND && SynchCommand != NCBCHAINSENDNA) {
|
|
RtlMoveMemory(Dest->ncb_callname, Src->ncb_callname, NCBNAMSZ);
|
|
}
|
|
Dest->ncb_rto = Src->ncb_rto;
|
|
Dest->ncb_sto = Src->ncb_sto;
|
|
|
|
//
|
|
// Translate an error code in a special case where netbios 2
|
|
// doesn't return an error
|
|
//
|
|
|
|
if (SynchCommand == NCBHANGUP &&
|
|
Src->ncb_retcode == NRC_SNUMOUT) {
|
|
|
|
Dest->ncb_retcode = NRC_GOODRET;
|
|
Dest->ncb_cmd_cplt = NRC_GOODRET;
|
|
} else {
|
|
Dest->ncb_retcode = Src->ncb_retcode;
|
|
Dest->ncb_cmd_cplt = Src->ncb_cmd_cplt;
|
|
}
|
|
}
|
|
|
|
|
|
// This is the post routine which is used by NetBiosSubmit
|
|
// It clears the user's semaphore (after doing the internal copy and cleanup)
|
|
static
|
|
VOID
|
|
_stdcall
|
|
Od2NetBiosSemaphoreClearPostRoutine(
|
|
IN PNCB pNcb
|
|
)
|
|
{
|
|
// A user's command has completed. copy the result to his NCB and clear his semaphore.
|
|
|
|
PNCB pOs2Ncb = ((PNCBX)pNcb)->original_pncb; // get user's NCB
|
|
HSYSSEM hUsersSemaphore = (HSYSSEM) ((PNCBX)pNcb)->original_ncb_post; // and semaphore handle
|
|
HANDLE Net16BiosHasCompleted = ((PNCBX)pNcb)->Net16BiosHasCompleted; // and notification event
|
|
APIRET RetCode;
|
|
|
|
// Wait for Net16Bios to complete its job
|
|
|
|
(VOID) NtWaitForSingleObject(Net16BiosHasCompleted, FALSE, NULL);
|
|
(VOID) NtClose(Net16BiosHasCompleted);
|
|
|
|
(VOID) InterlockedIncrement(&Od2MaxAsynchNcbs);
|
|
|
|
// Check if user's NCB space is still valid
|
|
|
|
try {
|
|
Od2ProbeForWrite(pOs2Ncb, sizeof(NCB), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
// invalidate user's cancellation address
|
|
*(PNCB *)pOs2Ncb->ncb_reserve = NULL;
|
|
|
|
// copy the results to the user's NCB
|
|
|
|
Od2CopyNcbResults(pOs2Ncb, pNcb, TRUE);
|
|
|
|
#if 1
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
Od2NcbDbgPrint(pNcb, pOs2Ncb, 3);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
// free our internal NCB
|
|
|
|
RtlFreeHeap(Od2Nb2Heap, 0, pNcb);
|
|
|
|
if (hUsersSemaphore == NULL) {
|
|
return;
|
|
}
|
|
|
|
// clear user's semaphore
|
|
|
|
if ((RetCode = DosSemClear(FARPTRTOFLAT(hUsersSemaphore))) != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Od2NetBiosSemaphoreClearPostRoutine: Failed to Clear User Semaphore RetCode = %d\n", RetCode));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
// This is the post routine which is used by Netbios (= 3.0)
|
|
// It calls the user's post routine (after doing the internal copy and cleanup)
|
|
static
|
|
VOID
|
|
_stdcall
|
|
Od2NetBiosPostRoutine(
|
|
IN PNCB pNcb
|
|
)
|
|
{
|
|
//
|
|
// A user's command has completed. copy the result to his NCB and launch his post routine.
|
|
//
|
|
|
|
PNCB pOs2Ncb = ((PNCBX)pNcb)->original_pncb; // get user's NCB
|
|
PVOID pUsersPostRoutine = (PVOID) ((PNCBX)pNcb)->original_ncb_post; // and post routine address
|
|
HANDLE Net16BiosHasCompleted = ((PNCBX)pNcb)->Net16BiosHasCompleted; // and notification event
|
|
APIRET RetCode;
|
|
BOOLEAN SpecialThread; // used to indicate a special addname thread
|
|
SEL TmpUserStackSel; // selector for netbios post routine user's stack in addname threads
|
|
SEL TmpUserStackAlias; // code alias for TmpUserStackSel
|
|
UCHAR SynchCommand;
|
|
|
|
//
|
|
// Wait for Net16Bios to complete its job
|
|
//
|
|
|
|
(VOID) NtWaitForSingleObject(Net16BiosHasCompleted, FALSE, NULL);
|
|
(VOID) NtClose(Net16BiosHasCompleted);
|
|
|
|
//
|
|
// Grab the command for later
|
|
//
|
|
|
|
SynchCommand = pNcb->ncb_command & ~ASYNCH;
|
|
|
|
//
|
|
// Check if user's NCB space is still valid
|
|
//
|
|
|
|
try {
|
|
Od2ProbeForWrite(pOs2Ncb, sizeof(NCB), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
//
|
|
// invalidate user's cancellation address
|
|
//
|
|
|
|
*(PNCB *)pOs2Ncb->ncb_reserve = NULL;
|
|
|
|
//
|
|
// copy the results to the user's NCB
|
|
//
|
|
|
|
Od2CopyNcbResults(pOs2Ncb, pNcb, FALSE);
|
|
|
|
#if 1
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
Od2NcbDbgPrint(pNcb, pOs2Ncb, 3);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
//
|
|
// free our internal NCB
|
|
//
|
|
|
|
RtlFreeHeap(Od2Heap, 0, pNcb);
|
|
|
|
if (pUsersPostRoutine == NULL) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Figure out if this is a special netbios addname thread.
|
|
// It must be attached separatly. If the TEB already has
|
|
// an environment then this is the worker thread, and it
|
|
// has already been attached.
|
|
// It is possible that this is the worker thread even though
|
|
// it's an addname-type command (this happens in case the
|
|
// worker fails to create an addname thread). This is OK
|
|
// The worker will be attached and detached now, and later
|
|
// re-attached if needed.
|
|
//
|
|
|
|
if (NtCurrentTeb()->EnvironmentPointer == NULL &&
|
|
(SynchCommand == NCBADDNAME ||
|
|
SynchCommand == NCBADDGRNAME ||
|
|
SynchCommand == NCBASTAT)
|
|
) {
|
|
|
|
SpecialThread = TRUE;
|
|
|
|
} else {
|
|
|
|
SpecialThread = FALSE;
|
|
}
|
|
|
|
if (SpecialThread ||
|
|
!Od2WorkerThreadIsAttached) {
|
|
|
|
//
|
|
// Do this only one time for worker thread, or
|
|
// once for every special addname thread
|
|
// This code adopts the thread and makes it
|
|
// an OS/2 thread.
|
|
//
|
|
|
|
//
|
|
// attach the thread to server tables
|
|
//
|
|
|
|
if ((RetCode = Od2AttachWinThreadToOs2()) != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Od2NetBiosPostRoutine: Failed to attach to Os2, RetCode = %d\n", RetCode));
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
//
|
|
// allocate a stack
|
|
//
|
|
|
|
if ((RetCode = DosAllocSeg(USERS_STACK_SIZE, &TmpUserStackSel, SEG_NONSHARED)) != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Od2NetBiosPostRoutine: Failed to allocate stack for user, unable to launch\n"));
|
|
KdPrint((" user's post routine. DosAllocSeg rc = %u\n", RetCode));
|
|
}
|
|
#endif
|
|
(VOID) Od2DosExit(EXIT_THREAD, 0L, 0xF0000000L); // this detaches the thread
|
|
return;
|
|
}
|
|
|
|
if ((RetCode = DosCreateCSAlias(TmpUserStackSel, &TmpUserStackAlias)) != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Od2NetBiosPostRoutine: Failed to code alias user's stack, DosCreateCSAlias rc = %u\n", RetCode));
|
|
}
|
|
#endif
|
|
(VOID) DosFreeSeg(TmpUserStackSel);
|
|
(VOID) Od2DosExit(EXIT_THREAD, 0L, 0xF0000000L); // this detaches the thread
|
|
return;
|
|
}
|
|
|
|
if (!SpecialThread) {
|
|
|
|
Od2UserStackSel = TmpUserStackSel;
|
|
Od2UserStackAlias = TmpUserStackAlias;
|
|
Od2WorkerThreadIsAttached = TRUE;
|
|
}
|
|
|
|
} else {
|
|
|
|
TmpUserStackSel = Od2UserStackSel;
|
|
TmpUserStackAlias = Od2UserStackAlias;
|
|
}
|
|
|
|
// set up and run user's post routine
|
|
|
|
Od2JumpTo16NetBiosPostDispatcher(pUsersPostRoutine, // 16-bit routine to jump to
|
|
SELTOFLAT(TmpUserStackSel), // flat ptr to user stack
|
|
USERS_STACK_SIZE, // stack size
|
|
TmpUserStackSel, // selector to user stack
|
|
TmpUserStackAlias, // code alias for user stack
|
|
(PVOID)FLATTOFARPTR(pOs2Ncb), // pointer to user's NCB
|
|
// pass it thru ES:BX
|
|
pOs2Ncb->ncb_retcode // pass through AX
|
|
);
|
|
|
|
if (SpecialThread) {
|
|
|
|
//
|
|
// Deallocate stack and detach thread.
|
|
// The worker thread always remains attached.
|
|
//
|
|
|
|
(VOID) DosFreeSeg(TmpUserStackAlias);
|
|
(VOID) DosFreeSeg(TmpUserStackSel);
|
|
(VOID) Od2DosExit(EXIT_THREAD, 0L, 0xF0000000L); // this only detaches the thread
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// This is the master Netbios 3.0 API. It checks the user's parameters,
|
|
// copies the NCB to an internal aligned NCB and calls win32 Netbios.
|
|
// some internal paramaters are attached to the NCB (see NCBX) on async calls
|
|
|
|
APIRET
|
|
Net16bios(
|
|
IN PNCB pOs2Ncb
|
|
)
|
|
{
|
|
PNCB pNcb;
|
|
PNCB pCancelNcb;
|
|
UCHAR rc;
|
|
UCHAR SynchCommand;
|
|
UCHAR Asynch;
|
|
HANDLE Net16BiosHasCompleted;
|
|
BOOLEAN Nb2Semantics;
|
|
BOOLEAN WillPost;
|
|
PVOID NbHeap;
|
|
NTSTATUS Status;
|
|
|
|
try {
|
|
Od2ProbeForWrite(pOs2Ncb, sizeof(NCB), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
pOs2Ncb->ncb_retcode = NRC_PENDING;
|
|
pOs2Ncb->ncb_cmd_cplt = NRC_PENDING;
|
|
|
|
SynchCommand = pOs2Ncb->ncb_command & ~ASYNCH;
|
|
Asynch = pOs2Ncb->ncb_command & ASYNCH;
|
|
|
|
if (*(PULONG)&pOs2Ncb->ncb_reserve[4] == NETBIOS2_SEMANTICS_SIGNATURE) {
|
|
*(PULONG)&pOs2Ncb->ncb_reserve[4] = 0;
|
|
Nb2Semantics = TRUE;
|
|
} else {
|
|
Nb2Semantics = FALSE;
|
|
}
|
|
|
|
//
|
|
// Allocate internal NCB
|
|
//
|
|
|
|
if (Nb2Semantics) {
|
|
NbHeap = Od2Nb2Heap;
|
|
} else {
|
|
NbHeap = Od2Heap;
|
|
}
|
|
|
|
pNcb = (PNCB) RtlAllocateHeap(NbHeap, 0, sizeof(NCBX));
|
|
|
|
ASSERT(((ULONG)pNcb & 3) == 0); // pointer must be DWORD aligned
|
|
|
|
if (pNcb == NULL) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16bios: Failed to RtlAllocateHeap internal NCB\n"));
|
|
}
|
|
#endif
|
|
pOs2Ncb->ncb_retcode = NRC_NORES;
|
|
pOs2Ncb->ncb_cmd_cplt = NRC_NORES;
|
|
// BUGBUG: should call post routine here if asynch.
|
|
return(NRC_NORES);
|
|
}
|
|
|
|
RtlMoveMemory(pNcb, pOs2Ncb, sizeof(NCB));
|
|
|
|
//
|
|
// If it is a netbios 2 reset then modify the new NCB to the protect mode parameters
|
|
//
|
|
// Note: this is not currently used, since we allow open for NB_REGULAR only
|
|
//
|
|
if (Nb2Semantics &&
|
|
SynchCommand == NCBRESET) {
|
|
if (pNcb->ncb_lsn == 0) {
|
|
pNcb->ncb_callname[0] = 6;
|
|
} else {
|
|
pNcb->ncb_callname[0] = pNcb->ncb_lsn;
|
|
}
|
|
if (pNcb->ncb_num == 0) {
|
|
pNcb->ncb_callname[1] = 12;
|
|
} else {
|
|
pNcb->ncb_callname[1] = pNcb->ncb_num;
|
|
}
|
|
pNcb->ncb_callname[2] = 16;
|
|
pNcb->ncb_callname[3] = 1;
|
|
pNcb->ncb_lsn = 0;
|
|
}
|
|
|
|
// Check user's input
|
|
|
|
switch (SynchCommand) {
|
|
case NCBSEND:
|
|
case NCBSENDNA:
|
|
case NCBDGSEND:
|
|
case NCBDGSENDBC:
|
|
|
|
if (pNcb->ncb_buffer != NULL) {
|
|
|
|
pNcb->ncb_buffer = FARPTRTOFLAT(pNcb->ncb_buffer);
|
|
|
|
try {
|
|
Od2ProbeForRead(pNcb->ncb_buffer, pNcb->ncb_length, 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NCBCHAINSEND:
|
|
case NCBCHAINSENDNA:
|
|
|
|
if (pNcb->ncb_buffer != NULL) {
|
|
|
|
PCHAR TmpPtr;
|
|
|
|
pNcb->ncb_buffer = FARPTRTOFLAT(pNcb->ncb_buffer);
|
|
|
|
try {
|
|
Od2ProbeForRead(pNcb->ncb_buffer, pNcb->ncb_length, 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if ((TmpPtr = *(PCHAR *)&pOs2Ncb->ncb_callname[2]) != NULL) {
|
|
|
|
TmpPtr = FARPTRTOFLAT(TmpPtr);
|
|
|
|
try {
|
|
Od2ProbeForRead(TmpPtr, *(PUSHORT)pNcb->ncb_callname, 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
*(PCHAR *)&pNcb->ncb_callname[2] = TmpPtr;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NCBFINDNAME:
|
|
case NCBRECV:
|
|
case NCBRECVANY:
|
|
case NCBDGRECV:
|
|
case NCBDGRECVBC:
|
|
case NCBASTAT:
|
|
case NCBSSTAT:
|
|
|
|
if (pNcb->ncb_buffer != NULL) {
|
|
|
|
pNcb->ncb_buffer = FARPTRTOFLAT(pNcb->ncb_buffer);
|
|
|
|
try {
|
|
Od2ProbeForWrite(pNcb->ncb_buffer, pNcb->ncb_length, 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NCBCANCEL:
|
|
|
|
if (pNcb->ncb_buffer != NULL) {
|
|
|
|
//
|
|
// Note: no need to call post routine on error
|
|
// return from here, because the cancel command
|
|
// is not allowed to be asynch.
|
|
//
|
|
|
|
pCancelNcb = (PNCB) FARPTRTOFLAT(pNcb->ncb_buffer);
|
|
|
|
try {
|
|
Od2ProbeForWrite(pCancelNcb, sizeof(NCB), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (pCancelNcb->ncb_cmd_cplt != NRC_PENDING) { // is the command still pending?
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16bios: Got request to cancel a non-pending NCB, ignoring it\n"));
|
|
}
|
|
#endif
|
|
RtlFreeHeap(NbHeap, 0, pNcb);
|
|
pOs2Ncb->ncb_retcode = NRC_CANCEL;
|
|
pOs2Ncb->ncb_cmd_cplt = NRC_CANCEL;
|
|
return(NRC_CANCEL);
|
|
}
|
|
|
|
pNcb->ncb_buffer = *(PUCHAR *)pCancelNcb->ncb_reserve;
|
|
|
|
if (pNcb->ncb_buffer == NULL) { // assume we've just completed it
|
|
// this is reasonable, since cmd_cplt == NRC_PENDING
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16bios: NCB completed during request to cancel\n"));
|
|
}
|
|
#endif
|
|
RtlFreeHeap(NbHeap, 0, pNcb);
|
|
pOs2Ncb->ncb_retcode = NRC_CANOCCR;
|
|
pOs2Ncb->ncb_cmd_cplt = NRC_CANOCCR;
|
|
return(NRC_CANOCCR);
|
|
}
|
|
|
|
try {
|
|
Od2ProbeForWrite(pNcb->ncb_buffer, sizeof(NCBX), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
|
|
//
|
|
// The user gave an invalid address
|
|
//
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16bios: Got an invalid NCB address to cancel, ignoring it\n"));
|
|
}
|
|
#endif
|
|
RtlFreeHeap(NbHeap, 0, pNcb);
|
|
pOs2Ncb->ncb_retcode = NRC_BADDR;
|
|
pOs2Ncb->ncb_cmd_cplt = NRC_BADDR;
|
|
return(NRC_BADDR);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
RtlZeroMemory(pNcb->ncb_reserve, 14);
|
|
|
|
//
|
|
// Set up async processing
|
|
//
|
|
|
|
if (Asynch) {
|
|
|
|
Status = NtCreateEvent(&Net16BiosHasCompleted,
|
|
EVENT_ALL_ACCESS,
|
|
NULL,
|
|
NotificationEvent,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Net16Bios: Can't create an event for synchronization of post routine, rc = %X\n", Status));
|
|
}
|
|
#endif
|
|
RtlFreeHeap(NbHeap, 0, pNcb);
|
|
pOs2Ncb->ncb_retcode = NRC_OSRESNOTAV;
|
|
pOs2Ncb->ncb_cmd_cplt = NRC_OSRESNOTAV;
|
|
// BUGBUG: should call post routine here.
|
|
return(NRC_OSRESNOTAV);
|
|
}
|
|
|
|
// BUGBUG: we must make sure the event is properly cleaned up if the thread terminates
|
|
// between here and the point it's signalled.
|
|
|
|
((PNCBX)pNcb)->original_pncb = pOs2Ncb;
|
|
((PNCBX)pNcb)->original_ncb_post = (ULONG) pNcb->ncb_post;
|
|
((PNCBX)pNcb)->Net16BiosHasCompleted = Net16BiosHasCompleted;
|
|
*(PNCB *)pOs2Ncb->ncb_reserve = pNcb;
|
|
|
|
if (Nb2Semantics) {
|
|
pNcb->ncb_post = Od2NetBiosSemaphoreClearPostRoutine;
|
|
} else {
|
|
pNcb->ncb_post = Od2NetBiosPostRoutine;
|
|
}
|
|
} else {
|
|
pNcb->ncb_post = NULL;
|
|
}
|
|
|
|
#if 1
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
Od2NcbDbgPrint(pNcb, pOs2Ncb, 1);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
//
|
|
// and go do it
|
|
//
|
|
|
|
if (Nb2Semantics) {
|
|
|
|
rc = Od2Netbios(pNcb, Od2NbDev, &WillPost);
|
|
|
|
} else {
|
|
|
|
rc = Netbios(pNcb);
|
|
|
|
//
|
|
// The following are the cases where win32 netbios does not call
|
|
// the post routine when called asynch:
|
|
// 1) bad ncb alignment (NRC_BADDR) -- won't happen
|
|
// 2) ncb_event and ncb_post both given (NRC_ILLCMD) -- won't happen
|
|
// 3) returns NRC_OPENERR
|
|
// this happens when win32 can't open \device\netbios
|
|
// or can't create a reserved event for sync processing.
|
|
// 4) sometimes when returns NRC_SYSTEM
|
|
// if win32 returns -- no post routine
|
|
// this happens when can't create worker thread
|
|
// or when can't create related events
|
|
// (event, addnameevent)
|
|
// if driver returns -- will call post routine
|
|
// 5) an access violation after chain send ncb completion when copying
|
|
// BigBuffer back to user space, or accessing the ncb
|
|
// internals (post, event).
|
|
//
|
|
// The only case we can't be sure about is NRC_SYSTEM. In this
|
|
// case it is better to assume the post routine will get called.
|
|
// the only damage that can be incurred in this way is that the
|
|
// ncb remains left behind on NbHeap, and Net16BiosHasCompleted
|
|
// event is not deleted. this isn't too bad, assuming this is
|
|
// a rare problem.
|
|
//
|
|
|
|
if (Asynch && rc != NRC_OPENERR) {
|
|
WillPost = TRUE;
|
|
} else {
|
|
WillPost = FALSE;
|
|
}
|
|
}
|
|
|
|
// copy results from internal NCB to user's NCB
|
|
|
|
Od2CopyNcbResults(pOs2Ncb, pNcb, Nb2Semantics);
|
|
|
|
#if 1
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
Od2NcbDbgPrint(pNcb, pOs2Ncb, 2);
|
|
KdPrint(("rc : %d\n", rc));
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
// Note that if the command was a CANCEL, the post routine of the cancelled NCB still gets called,
|
|
// and will clean up the cancelled NCB as needed
|
|
|
|
if (Asynch) {
|
|
if (WillPost) {
|
|
(VOID) NtSetEvent(Net16BiosHasCompleted, NULL);
|
|
} else {
|
|
(VOID) NtClose(Net16BiosHasCompleted);
|
|
RtlFreeHeap(NbHeap, 0, pNcb);
|
|
if (Nb2Semantics) {
|
|
(VOID) InterlockedIncrement(&Od2MaxAsynchNcbs);
|
|
}
|
|
}
|
|
} else {
|
|
RtlFreeHeap(NbHeap, 0, pNcb);
|
|
}
|
|
|
|
return((APIRET) rc);
|
|
}
|
|
|
|
|
|
//*******************
|
|
// Following are old Netbios APIs (lanman 2.x). We create a fictional logical network
|
|
// for each lan adapter in the system. This is done by using NCBENUM. NCBENUM gives
|
|
// us a list of all valid lana numbers in the system. We assign NET1 to the 1st lana
|
|
// NET2 to the 2nd lana and so on. The "default device" for NetBiosOpen and Submit is always
|
|
// NET DEFAULT_NET.
|
|
// The device handle which is used to operate a logical network is simply the NET
|
|
// number + 1. Handle 0 is equivalent to the default net.
|
|
//*******************
|
|
|
|
|
|
ULONG
|
|
Od2NetNumberToLanaIndex(
|
|
IN ULONG NetNumber
|
|
)
|
|
{
|
|
if (NetNumber == 0L) { // use default net ?
|
|
if (Od2LanaEnum.length >= DEFAULT_NET) {
|
|
return((ULONG)(DEFAULT_NET - 1));
|
|
} else {
|
|
return(0L);
|
|
}
|
|
} else {
|
|
if ((ULONG)Od2LanaEnum.length >= NetNumber) {
|
|
return(NetNumber - 1);
|
|
} else {
|
|
return((ULONG)-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
Od2ActivateLana(
|
|
IN ULONG NetNumber,
|
|
OUT PULONG pLanaIndex OPTIONAL
|
|
)
|
|
{
|
|
//
|
|
// This routine takes a net number, and makes sure netbios 2 is initialized
|
|
// and ready on that lana. overall netbios 2 initialization is done if necessary.
|
|
// if NetNumber is (-1), overall initialization is done, but not for a particular
|
|
// lana.
|
|
//
|
|
|
|
OS2_API_MSG m;
|
|
POS2_NETBIOS_MSG a = &m.u.Netbios2Request;
|
|
BOOLEAN InCrit = FALSE;
|
|
ULONG LanaIndex;
|
|
PVOID BaseAddress;
|
|
APIRET RetCode;
|
|
BOOLEAN RemoveLDTEntry = FALSE;
|
|
|
|
if (!Od2Netbios2Initialized) {
|
|
|
|
RtlEnterCriticalSection(&Od2NbSyncCrit);
|
|
|
|
if (!Od2Netbios2Initialized) { // check again in case we just did it
|
|
|
|
//
|
|
// allocate a special heap to hold the netbios 2 packets.
|
|
// we allocate this as a shared memory object in order that
|
|
// the heap have a unique address within each process. no
|
|
// sharing of memory is actually being done. the reason
|
|
// unique addresses are necessary is because the netbios
|
|
// driver gets confused about cancel requests when 2 processes
|
|
// have the same netbios packet address.
|
|
//
|
|
|
|
RetCode = DosAllocSharedMem(
|
|
&BaseAddress,
|
|
NULL, // no name
|
|
0x10000L, // reserve 64K for the heap
|
|
OBJ_GIVEABLE | PAG_READ | PAG_WRITE,
|
|
FALSE // Don't create LDT entry
|
|
);
|
|
|
|
if (RetCode != NO_ERROR) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Od2ActivateLana: DosAllocSharedMem failed, RetCode = %x\n", RetCode));
|
|
}
|
|
#endif
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
Od2Nb2Heap = RtlCreateHeap(
|
|
HEAP_GROWABLE,
|
|
BaseAddress,
|
|
0x10000L, // initial reserved amount
|
|
0L, // initial commit = 1 page
|
|
NULL, // standard lock
|
|
0L); // reserved
|
|
|
|
if (Od2Nb2Heap == NULL) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Od2ActivateLana: RtlCreateHeap failed\n"));
|
|
}
|
|
#endif
|
|
DosFreeMem(BaseAddress, &RemoveLDTEntry);
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
//
|
|
// call server to get initial device handle, lana enumeration
|
|
// initialize internal lanastate
|
|
//
|
|
|
|
if (NetNumber == (ULONG)-1) {
|
|
a->RequestType = NB2_INIT;
|
|
} else {
|
|
a->RequestType = NB2_INIT_LANA;
|
|
a->NetNumber = (UCHAR) NetNumber;
|
|
}
|
|
|
|
m.ReturnedErrorValue = NO_ERROR;
|
|
Od2CallSubsystem(&m, NULL, Os2Netbios2Reqst, sizeof(*a));
|
|
|
|
if (!NT_SUCCESS(a->ReturnStatus)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("Od2ActivateLana: Call to server for init failed, Status = %lx\n", a->ReturnStatus));
|
|
}
|
|
#endif
|
|
RtlDestroyHeap(Od2Nb2Heap);
|
|
DosFreeMem(BaseAddress, &RemoveLDTEntry);
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
return(a->ReturnStatus);
|
|
}
|
|
|
|
Od2LanaEnum.length = a->LanaEnumLength;
|
|
RtlMoveMemory(Od2LanaEnum.lana, a->LanaEnum, MAX_LANA);
|
|
RtlZeroMemory(Od2LanaState, sizeof(Od2LanaState));
|
|
Od2NbDev = a->hDev;
|
|
Od2MaxAsynchNcbs = (LONG) MAX_ASYNCH_NCBS;
|
|
|
|
Od2Netbios2Initialized = TRUE;
|
|
|
|
if (NetNumber != (ULONG)-1) {
|
|
if (a->RetCode != NB2ERR_INVALID_LANA) {
|
|
|
|
LanaIndex = Od2NetNumberToLanaIndex(NetNumber);
|
|
|
|
Od2LanaState[LanaIndex] |= 0x1;
|
|
|
|
if (ARGUMENT_PRESENT(pLanaIndex)) {
|
|
*pLanaIndex = LanaIndex;
|
|
}
|
|
} else {
|
|
if (ARGUMENT_PRESENT(pLanaIndex)) {
|
|
*pLanaIndex = (ULONG) -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
InCrit = TRUE;
|
|
}
|
|
|
|
if (NetNumber == (ULONG)-1) {
|
|
if (InCrit) {
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
LanaIndex = Od2NetNumberToLanaIndex(NetNumber);
|
|
|
|
if (LanaIndex == (ULONG)-1) {
|
|
|
|
if (ARGUMENT_PRESENT(pLanaIndex)) {
|
|
*pLanaIndex = (ULONG) -1;
|
|
}
|
|
if (InCrit) {
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
if (!(Od2LanaState[LanaIndex] & 0x1)) {
|
|
|
|
if (!InCrit) {
|
|
|
|
RtlEnterCriticalSection(&Od2NbSyncCrit);
|
|
InCrit = TRUE;
|
|
|
|
if (Od2LanaState[LanaIndex] & 0x1) { // check again in case we just did it
|
|
goto Od2LanaNumGood;
|
|
}
|
|
}
|
|
|
|
//
|
|
// call server to init lana
|
|
//
|
|
|
|
if (Od2LanaState[LanaIndex] & 0x2) {
|
|
Od2LanaState[LanaIndex] &= ~0x2;
|
|
Od2LanaState[LanaIndex] |= 0x1;
|
|
goto Od2LanaNumGood;
|
|
}
|
|
|
|
a->RequestType = NB2_LANA;
|
|
a->NetNumber = (UCHAR) NetNumber;
|
|
|
|
m.ReturnedErrorValue = NO_ERROR;
|
|
Od2CallSubsystem(&m, NULL, Os2Netbios2Reqst, sizeof(*a));
|
|
|
|
if (!NT_SUCCESS(a->ReturnStatus)) {
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
return(a->ReturnStatus);
|
|
}
|
|
|
|
if (a->RetCode != NB2ERR_INVALID_LANA) {
|
|
|
|
Od2LanaState[LanaIndex] |= 0x1;
|
|
goto Od2LanaNumGood;
|
|
|
|
} else {
|
|
if (ARGUMENT_PRESENT(pLanaIndex)) {
|
|
*pLanaIndex = (ULONG) -1;
|
|
}
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
}
|
|
|
|
Od2LanaNumGood:
|
|
|
|
if (ARGUMENT_PRESENT(pLanaIndex)) {
|
|
*pLanaIndex = LanaIndex;
|
|
}
|
|
|
|
if (InCrit) {
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16BiosClose(
|
|
ULONG hDevName
|
|
)
|
|
{
|
|
// NCB Ncb;
|
|
ULONG LanaIndex;
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosClose() called, hDevName = %lu\n", hDevName));
|
|
}
|
|
#endif
|
|
|
|
if (hDevName == 0) {
|
|
return(NERR_Success); // dummy close for the "default handle"
|
|
}
|
|
|
|
if (!Od2Netbios2Initialized) { // we haven't been initialized at all
|
|
return(NERR_NetNotStarted);
|
|
}
|
|
|
|
LanaIndex = Od2NetNumberToLanaIndex(hDevName);
|
|
|
|
if (LanaIndex == (ULONG)-1) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosClose: invalid hDevName = %lu\n", hDevName));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// check if it's already closed...
|
|
//
|
|
|
|
if (!(Od2LanaState[LanaIndex] & 0x1)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosClose: already closed hDevName = %lu\n", hDevName));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
RtlEnterCriticalSection(&Od2NbSyncCrit);
|
|
|
|
//
|
|
// recheck in case we just closed it.
|
|
//
|
|
|
|
if (!(Od2LanaState[LanaIndex] & 0x1)) {
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosClose: already closed hDevName = %lu\n", hDevName));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// we mark the lana as pseudo-closed. It won't be used anymore
|
|
// until it's reopened.
|
|
//
|
|
|
|
Od2LanaState[LanaIndex] &= ~0x1;
|
|
Od2LanaState[LanaIndex] |= 0x2;
|
|
|
|
|
|
//
|
|
// BUGBUG: We can no longer reset the adapter in order to
|
|
// cancel all pending ncbs on a particular lana. Currently,
|
|
// there is no other way to do this, so we skip cancelling
|
|
// pending ncbs, and hope there won't be a problem.
|
|
//
|
|
// Note: a way to do this might be to issue an NtCancelIoFile()
|
|
// from the netbios worker thread. But this will cancel on all
|
|
// lana.
|
|
//
|
|
|
|
#if 0
|
|
// Reset the corresponding adapter so all pending NCBs get cancelled
|
|
|
|
RtlZeroMemory(&Ncb, sizeof(NCB));
|
|
Ncb.ncb_command = NCBRESET;
|
|
Ncb.ncb_lana_num = Od2LanaEnum.lana[LanaIndex];
|
|
|
|
Net16bios(&Ncb);
|
|
|
|
if (Ncb.ncb_retcode != NRC_GOODRET) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosClose: Unable to reset adapter %lu, retcode = %x\n", (ULONG)Ncb.ncb_lana_num, (ULONG)Ncb.ncb_retcode));
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
RtlLeaveCriticalSection(&Od2NbSyncCrit);
|
|
return(NERR_Success);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16BiosEnum(
|
|
PCHAR pszServer,
|
|
LONG sLevel,
|
|
PCHAR pbBuffer,
|
|
ULONG cbBuffer,
|
|
PUSHORT pcEntriesRead,
|
|
PUSHORT pcTotalAvail
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG strucsiz;
|
|
UCHAR i;
|
|
struct netbios_info_0 nb0;
|
|
struct netbios_info_1 nb1;
|
|
|
|
try {
|
|
if ((pszServer != NULL) && (*pszServer != '\0')) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosEnum() for a remote server is not implemented yet\n"));
|
|
}
|
|
#endif
|
|
return(ERROR_NOT_SUPPORTED);
|
|
}
|
|
|
|
Od2ProbeForWrite(pbBuffer, cbBuffer, 1);
|
|
Od2ProbeForWrite(pcEntriesRead, sizeof(USHORT), 1);
|
|
Od2ProbeForWrite(pcTotalAvail, sizeof(USHORT), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sLevel != 0 && sLevel != 1) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosEnum() Level %d not legal\n", sLevel));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_LEVEL);
|
|
}
|
|
|
|
Status = Od2ActivateLana(
|
|
(ULONG) -1,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosEnum() Od2ActivateLana failed, Status = %lx\n", Status));
|
|
}
|
|
#endif
|
|
return(NERR_NetNotStarted);
|
|
}
|
|
|
|
*pcTotalAvail = (USHORT) Od2LanaEnum.length;
|
|
*pcEntriesRead = 0;
|
|
|
|
strucsiz = sLevel == 0 ? sizeof(nb0) : sizeof(nb1);
|
|
|
|
for (i = 0; i < Od2LanaEnum.length && cbBuffer >= strucsiz; i++) {
|
|
if (sLevel == 0) {
|
|
RtlZeroMemory(&nb0, strucsiz);
|
|
strcpy(nb0.nb0_net_name, "NET");
|
|
_itoa((int)i+1, &nb0.nb0_net_name[3], 10);
|
|
RtlMoveMemory(pbBuffer, &nb0, strucsiz);
|
|
} else { // sLevel == 1
|
|
RtlZeroMemory(&nb1, strucsiz);
|
|
strcpy(nb1.nb1_net_name, "NET");
|
|
_itoa((int)i+1, &nb1.nb1_net_name[3], 10);
|
|
strcpy(nb1.nb1_driver_name, "VrtWnNB$");
|
|
nb1.nb1_lana_num = Od2LanaEnum.lana[i];
|
|
|
|
// put some fictive information in it...
|
|
|
|
nb1.nb1_driver_type = NB_TYPE_NCB;
|
|
nb1.nb1_net_status = NB_OPEN_REGULAR|NB_LAN_MANAGED;
|
|
nb1.nb1_net_bandwidth = 10000000L;
|
|
nb1.nb1_max_sess = 255;
|
|
nb1.nb1_max_ncbs = 255;
|
|
nb1.nb1_max_names = 255;
|
|
|
|
RtlMoveMemory(pbBuffer, &nb1, strucsiz);
|
|
}
|
|
pbBuffer += strucsiz;
|
|
cbBuffer -= strucsiz;
|
|
(*pcEntriesRead)++;
|
|
}
|
|
|
|
if (*pcEntriesRead < (USHORT)Od2LanaEnum.length) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosEnum: returning ERROR_MORE_DATA\n"));
|
|
}
|
|
#endif
|
|
return(ERROR_MORE_DATA);
|
|
}
|
|
return(NERR_Success);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16BiosGetInfo(
|
|
PCHAR pszServer,
|
|
PCHAR pszNetBiosName,
|
|
LONG sLevel,
|
|
PCHAR pbBuffer,
|
|
ULONG cbBuffer,
|
|
PUSHORT pcbTotalAvail
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG strucsiz;
|
|
ULONG NetNumber;
|
|
ULONG LanaIndex;
|
|
struct netbios_info_0 nb0;
|
|
struct netbios_info_1 nb1;
|
|
|
|
try {
|
|
if ((pszServer != NULL) && (*pszServer != '\0')) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosGetInfo() for a remote server is not implemented yet\n"));
|
|
}
|
|
#endif
|
|
return(ERROR_NOT_SUPPORTED);
|
|
}
|
|
|
|
PROBE_STRING(pszNetBiosName);
|
|
Od2ProbeForWrite(pbBuffer, cbBuffer, 1);
|
|
Od2ProbeForWrite(pcbTotalAvail, sizeof(USHORT), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (sLevel != 0 && sLevel != 1) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosGetInfo() Level %d not legal\n", sLevel));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_LEVEL);
|
|
}
|
|
|
|
strucsiz = sLevel == 0 ? sizeof(nb0) : sizeof(nb1);
|
|
|
|
if (cbBuffer < strucsiz) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosGetInfo: user buffer too small\n"));
|
|
}
|
|
#endif
|
|
return(NERR_BufTooSmall);
|
|
}
|
|
|
|
if (pszNetBiosName == NULL || *pszNetBiosName == '\0') {
|
|
NetNumber = 0;
|
|
} else {
|
|
if (_strnicmp(pszNetBiosName, "NET", 3)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosGetInfo: Bad network name: %s\n", pszNetBiosName));
|
|
}
|
|
#endif
|
|
return(ERROR_BAD_NETPATH);
|
|
}
|
|
|
|
NetNumber = atol(pszNetBiosName+3);
|
|
}
|
|
|
|
Status = Od2ActivateLana(
|
|
(ULONG) -1,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosGetInfo() Od2ActivateLana failed, Status = %lx\n", Status));
|
|
}
|
|
#endif
|
|
return(NERR_NetNotStarted);
|
|
}
|
|
|
|
LanaIndex = Od2NetNumberToLanaIndex(NetNumber);
|
|
|
|
if (LanaIndex == (ULONG) -1) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosGetInfo: Bad network name: %s\n", pszNetBiosName));
|
|
}
|
|
#endif
|
|
return(ERROR_BAD_NETPATH);
|
|
}
|
|
|
|
*pcbTotalAvail = (USHORT) strucsiz;
|
|
|
|
if (sLevel == 0) {
|
|
RtlZeroMemory(&nb0, strucsiz);
|
|
strcpy(nb0.nb0_net_name, pszNetBiosName);
|
|
RtlMoveMemory(pbBuffer, &nb0, strucsiz);
|
|
} else { // sLevel == 1
|
|
RtlZeroMemory(&nb1, strucsiz);
|
|
strcpy(nb1.nb1_net_name, pszNetBiosName);
|
|
strcpy(nb1.nb1_driver_name, "VrtWnNB$");
|
|
nb1.nb1_lana_num = Od2LanaEnum.lana[LanaIndex];
|
|
|
|
// put some fictive information in it...
|
|
|
|
nb1.nb1_driver_type = NB_TYPE_NCB;
|
|
nb1.nb1_net_status = NB_OPEN_REGULAR|NB_LAN_MANAGED;
|
|
nb1.nb1_net_bandwidth = 10000000L;
|
|
nb1.nb1_max_sess = 255;
|
|
nb1.nb1_max_ncbs = 255;
|
|
nb1.nb1_max_names = 255;
|
|
|
|
RtlMoveMemory(pbBuffer, &nb1, strucsiz);
|
|
}
|
|
|
|
return(NERR_Success);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Net16BiosOpen(
|
|
PCHAR pszDevName,
|
|
PCHAR pszReserved,
|
|
ULONG usOpenOpt,
|
|
PUSHORT phDevName
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG NetNumber;
|
|
ULONG LanaIndex;
|
|
|
|
UNREFERENCED_PARAMETER(pszReserved);
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosOpen() called\n"));
|
|
}
|
|
#endif
|
|
|
|
try {
|
|
PROBE_STRING(pszDevName);
|
|
Od2ProbeForWrite(phDevName, sizeof(USHORT), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (usOpenOpt < NB_REGULAR ||
|
|
usOpenOpt > NB_EXCLUSIVE) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosOpen() illegal usOpenOpt = %lx\n", usOpenOpt));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
if (usOpenOpt != NB_REGULAR) { // we only support NB_REGULAR for now
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosOpen() unsupported usOpenOpt = %lx\n", usOpenOpt));
|
|
}
|
|
#endif
|
|
return(ERROR_ACCESS_DENIED);
|
|
}
|
|
|
|
if (pszDevName == NULL || *pszDevName == '\0') {
|
|
NetNumber = 0L;
|
|
} else {
|
|
if (_strnicmp(pszDevName, "NET", 3)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosOpen: Bad network name: %s\n", pszDevName));
|
|
}
|
|
#endif
|
|
return(ERROR_BAD_NETPATH);
|
|
}
|
|
|
|
NetNumber = atol(pszDevName+3);
|
|
}
|
|
|
|
if (NetNumber > 0xffL) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosOpen: Bad network name: %s\n", pszDevName));
|
|
}
|
|
#endif
|
|
return(ERROR_BAD_NETPATH);
|
|
}
|
|
|
|
Status = Od2ActivateLana(
|
|
NetNumber,
|
|
&LanaIndex);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosOpen() Od2ActivateLana failed, Status = %lx\n", Status));
|
|
}
|
|
#endif
|
|
return(NERR_NetNotStarted);
|
|
}
|
|
|
|
if (LanaIndex == (ULONG) -1) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosOpen: Bad network name: %s\n", pszDevName));
|
|
}
|
|
#endif
|
|
return(ERROR_BAD_NETPATH);
|
|
}
|
|
|
|
if (NetNumber != 0) {
|
|
*phDevName = (USHORT) NetNumber;
|
|
} else {
|
|
if (Od2LanaEnum.length >= DEFAULT_NET) {
|
|
*phDevName = (USHORT) DEFAULT_NET;
|
|
} else {
|
|
*phDevName = (USHORT) 1;
|
|
}
|
|
}
|
|
|
|
return(NERR_Success);
|
|
}
|
|
|
|
|
|
// Old lanman NetBiosSubmit. Generally depends on the newer Netbios 3.0 (Net16bios)
|
|
// however, this implements the following differences:
|
|
//
|
|
// - on async requests, a semaphore is cleared instead of calling a post routine
|
|
// - implements the possiblity of NCB chaining which is unavailable with Net16bios
|
|
// - does an automatic open of the default lana if necessary
|
|
//
|
|
|
|
APIRET
|
|
Net16BiosSubmit(
|
|
IN ULONG hDevName,
|
|
IN ULONG NcbOpt,
|
|
IN OUT PVOID pNCB
|
|
)
|
|
{
|
|
PNCB pNcb;
|
|
PCHAR OrigSegBase;
|
|
NTSTATUS Status;
|
|
ULONG LanaIndex;
|
|
BOOLEAN FirstRound;
|
|
BOOLEAN CancelChain;
|
|
USHORT Link;
|
|
UCHAR OrigLanaNum;
|
|
UCHAR SynchCommand;
|
|
UCHAR Asynch;
|
|
UCHAR rc;
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosSubmit() called\n"));
|
|
}
|
|
#endif
|
|
|
|
if (NcbOpt > 3) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosSubmit called with an invalid NcbOpt = %lu\n", NcbOpt));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
if (hDevName > 0xffL) {
|
|
|
|
LanaIndex = (ULONG)-1;
|
|
|
|
} else if (hDevName == 0L) { // use default net?
|
|
|
|
//
|
|
// do a default open of device handle 0
|
|
//
|
|
|
|
Status = Od2ActivateLana(
|
|
hDevName,
|
|
&LanaIndex);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosSubmit: Od2ActivateLana failed, Status= %lx\n", Status));
|
|
}
|
|
#endif
|
|
return(NERR_NetNotStarted);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Initialize, and check if the handle is open
|
|
//
|
|
|
|
Status = Od2ActivateLana(
|
|
(ULONG) -1,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosSubmit: Od2ActivateLana failed, Status= %lx\n", Status));
|
|
}
|
|
#endif
|
|
return(NERR_NetNotStarted);
|
|
}
|
|
|
|
LanaIndex = Od2NetNumberToLanaIndex(hDevName);
|
|
|
|
if (LanaIndex != (ULONG) -1) {
|
|
|
|
if (!(Od2LanaState[LanaIndex] & 0x1)) { // lana closed?
|
|
LanaIndex = (ULONG) -1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (LanaIndex == (ULONG) -1) {
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosSubmit: Bad handle, hDevName = %lu\n", hDevName));
|
|
}
|
|
#endif
|
|
return(ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
//
|
|
// NcbOpt == 1 implies that we should retry the NCB on some types of errors.
|
|
// Since the LanMan programmer's reference does not document which errors cause a
|
|
// retry, we shall not retry anything for the present
|
|
//
|
|
|
|
for (FirstRound = TRUE, CancelChain = FALSE; ; FirstRound = FALSE) {
|
|
|
|
if (NcbOpt > 1) {
|
|
|
|
if (FirstRound) {
|
|
OrigSegBase = SELTOFLAT(FLATTOSEL(pNCB));
|
|
}
|
|
|
|
try {
|
|
Link = *(PUSHORT)pNCB;
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (Link == 0xffff) {
|
|
if (FirstRound) {
|
|
return(NERR_Success);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
pNcb = (PNCB)((PCHAR)pNCB+sizeof(USHORT));
|
|
pNCB = (PVOID)(OrigSegBase + Link);
|
|
|
|
try {
|
|
Od2ProbeForWrite(pNcb, sizeof(NCB), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
if (CancelChain) {
|
|
pNcb->ncb_retcode = NRC_CMDCAN;
|
|
pNcb->ncb_cmd_cplt = NRC_CMDCAN;
|
|
continue;
|
|
}
|
|
} else {
|
|
if (FirstRound) {
|
|
pNcb = (PNCB) pNCB;
|
|
|
|
try {
|
|
Od2ProbeForWrite(pNcb, sizeof(NCB), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
}
|
|
}
|
|
|
|
pNcb->ncb_retcode = NRC_PENDING;
|
|
pNcb->ncb_cmd_cplt = NRC_PENDING;
|
|
|
|
SynchCommand = pNcb->ncb_command & ~ASYNCH;
|
|
Asynch = pNcb->ncb_command & ASYNCH;
|
|
|
|
//
|
|
// If it is a netbios 2 reset - disallow, since we only allow open for NB_REGULAR.
|
|
//
|
|
|
|
if (SynchCommand == NCBRESET) {
|
|
pNcb->ncb_retcode = NRC_ILLCMD;
|
|
pNcb->ncb_cmd_cplt = NRC_ILLCMD;
|
|
rc = NRC_ILLCMD;
|
|
goto ErrorHandling;
|
|
}
|
|
|
|
if (Asynch) {
|
|
|
|
LONG Count;
|
|
|
|
Count = InterlockedDecrement(&Od2MaxAsynchNcbs);
|
|
|
|
if (Count < 0) {
|
|
|
|
(VOID) InterlockedIncrement(&Od2MaxAsynchNcbs);
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosSubmit: max asynch ncb count exceeded\n"));
|
|
}
|
|
#endif
|
|
pNcb->ncb_retcode = NRC_NORES;
|
|
pNcb->ncb_cmd_cplt = NRC_NORES;
|
|
rc = NRC_NORES;
|
|
goto ErrorHandling;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// switch lananum to represent the "device driver"
|
|
// originally this was done only if the lananum is 0,
|
|
// but it is now done always
|
|
//
|
|
|
|
OrigLanaNum = pNcb->ncb_lana_num;
|
|
pNcb->ncb_lana_num = Od2LanaEnum.lana[LanaIndex];
|
|
|
|
//
|
|
// mark this as a netbios 2 ncb for special processing
|
|
//
|
|
|
|
*(PULONG)&pNcb->ncb_reserve[4] = NETBIOS2_SEMANTICS_SIGNATURE;
|
|
|
|
Net16bios(pNcb);
|
|
|
|
rc = pNcb->ncb_retcode;
|
|
pNcb->ncb_lana_num = OrigLanaNum;
|
|
|
|
ErrorHandling:
|
|
|
|
if (NcbOpt == 0) {
|
|
break;
|
|
} else if (NcbOpt == 1) {
|
|
|
|
// for implementing error-retry on a single NCB, check the error code here
|
|
// and if it should be retried simply "continue" instead of "break"
|
|
break;
|
|
|
|
} else if (NcbOpt == 3) { // stop on error
|
|
CancelChain = TRUE;
|
|
}
|
|
|
|
// if proceed-on-error, continue the loop
|
|
}
|
|
|
|
switch (rc) {
|
|
case NRC_GOODRET:
|
|
case NRC_PENDING:
|
|
return(NERR_Success);
|
|
|
|
default:
|
|
#if DBG
|
|
IF_OD2_DEBUG( NET ) {
|
|
KdPrint(("NetBiosSubmit: Final return code = %x\n", (ULONG)rc));
|
|
}
|
|
#endif
|
|
return((APIRET)rc | 0x100);
|
|
}
|
|
}
|
|
|
|
APIRET
|
|
DosINetTransaction(
|
|
IN LPSTR ServerName,
|
|
IN LPBYTE SendParmBuffer,
|
|
IN DWORD SendParmBufLen,
|
|
IN LPBYTE SendDataBuffer,
|
|
IN DWORD SendDataBufLen,
|
|
OUT LPBYTE ReceiveParmBuffer,
|
|
IN DWORD ReceiveParmBufLen,
|
|
IN LPBYTE ReceiveDataBuffer,
|
|
IN OUT LPDWORD ReceiveDataBufLen,
|
|
IN BOOL NullSessionFlag
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends a transaction request to a server and receives a response
|
|
|
|
Arguments:
|
|
|
|
ServerName - to send request to
|
|
SendParmBuffer - send parameters
|
|
SendParmBufLen - length of send parameters
|
|
SendDataBuffer - send data
|
|
SendDataBufLen - length of send data
|
|
ReceiveParmBuffer - receive parameter buffer
|
|
ReceiveParmBufLen - length of receive parameter buffer
|
|
ReceiveDataBuffer - where to receive data
|
|
ReceiveDataBufLen - length of data buffer
|
|
NullSessionFlag - set if we are to use a null session
|
|
|
|
Return Value:
|
|
|
|
APIRET
|
|
Success - NERR_Success
|
|
Failure -
|
|
|
|
--*/
|
|
|
|
{
|
|
APIRET status;
|
|
|
|
status = RxpTransactSmb((USHORT *)ServerName,
|
|
|
|
//
|
|
// BUGBUG - transport name?
|
|
//
|
|
|
|
(LPTSTR)NULL,
|
|
SendParmBuffer,
|
|
SendParmBufLen,
|
|
SendDataBuffer,
|
|
SendDataBufLen,
|
|
ReceiveParmBuffer,
|
|
ReceiveParmBufLen,
|
|
ReceiveDataBuffer,
|
|
ReceiveDataBufLen,
|
|
NullSessionFlag
|
|
);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
APIRET
|
|
DosIRemoteApi(
|
|
IN DWORD ApiNumber,
|
|
IN LPSTR ServerNamePointer,
|
|
IN LPSTR ParameterDescriptor,
|
|
IN LPSTR DataDescriptor,
|
|
IN LPSTR AuxDescriptor,
|
|
IN ULONG NullSessionFlag
|
|
)
|
|
{
|
|
APIRET rc;
|
|
|
|
#if DBG
|
|
USHORT tid, pid;
|
|
|
|
IF_OD2_DEBUG ( APIS ) {
|
|
pid = (USHORT)(Od2Process->Pib.ProcessId);
|
|
tid = (USHORT)(Od2CurrentThreadId());
|
|
|
|
if ((Os2DebugTID == 0) || (Os2DebugTID == tid))
|
|
{
|
|
KdPrint(("[PID %d: TID %d] %s\n",
|
|
pid, tid, Os2NetAPIName[ApiNumber]));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
rc = VrRemoteApi(
|
|
ApiNumber,
|
|
ServerNamePointer,
|
|
ParameterDescriptor,
|
|
DataDescriptor,
|
|
AuxDescriptor,
|
|
(UCHAR)NullSessionFlag
|
|
);
|
|
return rc;
|
|
}
|
|
|
|
APIRET
|
|
VrEncryptSES(
|
|
IN LPSTR ServerNamePointer,
|
|
IN LPSTR passwordPointer, // Input password (Not encripted)
|
|
IN LPSTR encryptedLmOwfPassword // output password (encripted)
|
|
);
|
|
|
|
APIRET
|
|
DosIEncryptSES(
|
|
IN LPSTR ServerNamePointer,
|
|
IN LPSTR passwordPointer, // Input password (Not encripted)
|
|
IN LPSTR encryptedLmOwfPassword // output password (encripted)
|
|
)
|
|
{
|
|
APIRET rc;
|
|
|
|
rc = VrEncryptSES(ServerNamePointer, passwordPointer,
|
|
encryptedLmOwfPassword);
|
|
return(rc);
|
|
}
|
|
|
|
APIRET
|
|
NetIWkstaGetUserInfo (LPBYTE UserName, LPBYTE LogonServer,
|
|
LPBYTE LogonDomain, LPBYTE OtherDomains, LPBYTE WsName)
|
|
{
|
|
//TCHAR Server[UNCLEN];
|
|
LPBYTE BufPtr;
|
|
NET_API_STATUS rc;
|
|
PWKSTA_USER_INFO_1 pInfo1;
|
|
PWKSTA_INFO_100 pInfo2;
|
|
|
|
rc = NetWkstaUserGetInfo(NULL, 1L, &BufPtr);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
pInfo1 = (PWKSTA_USER_INFO_1) BufPtr;
|
|
|
|
UT2ANSIstrcpy(UserName, pInfo1->wkui1_username);
|
|
|
|
strcpy(LogonServer, "\\\\");
|
|
UT2ANSIstrcpy(LogonServer + 2, pInfo1->wkui1_logon_server);
|
|
|
|
UT2ANSIstrcpy(LogonDomain, pInfo1->wkui1_logon_domain);
|
|
|
|
UT2ANSIstrcpy(OtherDomains, pInfo1->wkui1_oth_domains);
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
|
|
rc = NetWkstaGetInfo(0L, 100L, &BufPtr);
|
|
|
|
if (rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
pInfo2 = (PWKSTA_INFO_100) BufPtr;
|
|
|
|
UT2ANSIstrcpy(WsName, pInfo2->wki100_computername);
|
|
|
|
NetApiBufferFree(BufPtr);
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|