Windows NT 4.0 source code leak
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

/*++
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;
}