|
|
/*++
Copyright (c) 1993-1995 Microsoft Corporation
Module Name:
nwnetapi.c
Abstract:
Author:
Arthur Hanson (arth) 16-Jun-1994
Revision History:
--*/
#include "globals.h"
#include <nwapi32.h>
#include "nwconv.h"
#include "convapi.h"
#include "nwnetapi.h"
#include "statbox.h"
#define SUPERVISOR "SUPERVISOR"
#define ACCOUNT_LOCKOUT "ACCT_LOCKOUT"
#define GROUP_MEMBERS "GROUP_MEMBERS"
#define GROUPS_IM_IN "GROUPS_I'M_IN"
#define IDENTIFICATION "IDENTIFICATION"
#define LOGIN_CONTROL "LOGIN_CONTROL"
#define PS_OPERATORS "PS_OPERATORS"
#define SECURITY_EQUALS "SECURITY_EQUALS"
#define USER_DEFAULTS "USER_DEFAULTS"
#define MS_EXTENDED_NCPS "MS_EXTENDED_NCPS"
#define FPNW_PDC "FPNWPDC"
#ifdef DEBUG
int ErrorBoxRetry(LPTSTR szFormat, ...); #endif
// Couple of NetWare specific data structures - see NetWare programming books for
// info on these structures
#pragma pack(1)
typedef struct tagLoginControl { BYTE byAccountExpires[3]; BYTE byAccountDisabled; BYTE byPasswordExpires[3]; BYTE byGraceLogins; WORD wPasswordInterval; BYTE byGraceLoginReset; BYTE byMinPasswordLength; WORD wMaxConnections; BYTE byLoginTimes[42]; BYTE byLastLogin[6]; BYTE byRestrictions; BYTE byUnused; long lMaxDiskBlocks; WORD wBadLogins; LONG lNextResetTime; BYTE byBadLoginAddr[12]; }; // tagLoginControl
#pragma pack()
typedef struct tagAccountBalance { long lBalance; long lCreditLimit; }; // tagAccountBalance
typedef struct tagUserDefaults { BYTE byAccountExpiresYear; BYTE byAccountExpiresMonth; BYTE byAccountExpiresDay; BYTE byRestrictions; WORD wPasswordInterval; BYTE byGraceLoginReset; BYTE byMinPasswordLength; WORD wMaxConnections; BYTE byLoginTimes[42]; long lBalance; long lCreditLimit; long lMaxDiskBlocks; }; // tagUserDefaults
// define the mapping for FILE objects. Note: we only use GENERIC and
// STANDARD bits!
RIGHTS_MAPPING FileRightsMapping = { 0, { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS }, { { NW_FILE_READ, GENERIC_READ}, { NW_FILE_WRITE, GENERIC_WRITE}, { NW_FILE_CREATE, 0}, { NW_FILE_DELETE, GENERIC_WRITE|DELETE}, { NW_FILE_PERM, WRITE_DAC}, { NW_FILE_SCAN, 0}, { NW_FILE_MODIFY, GENERIC_WRITE}, { NW_FILE_SUPERVISOR, GENERIC_ALL}, { 0, 0 } } } ;
RIGHTS_MAPPING DirRightsMapping = { CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS }, { { NW_FILE_READ, GENERIC_READ|GENERIC_EXECUTE}, { NW_FILE_WRITE, GENERIC_WRITE}, { NW_FILE_CREATE, GENERIC_WRITE}, { NW_FILE_DELETE, DELETE}, { NW_FILE_PERM, WRITE_DAC}, { NW_FILE_SCAN, GENERIC_READ}, { NW_FILE_MODIFY, GENERIC_WRITE}, { NW_FILE_SUPERVISOR, GENERIC_ALL}, { 0, 0 } } } ;
VOID UserInfoLog(LPTSTR UserName, struct tagLoginControl tag); VOID Moveit(NWCONN_HANDLE Conn, LPTSTR UserName); VOID UserRecInit(NT_USER_INFO *UserInfo); BOOL IsNCPServerFPNW(NWCONN_HANDLE Conn);
static NWCONN_HANDLE CachedConn = 0;
static TCHAR CachedServer[MAX_SERVER_NAME_LEN + 1]; static DWORD CachedServerTime = 0xffffffff; // minutes since 1985...
typedef struct _PRINT_SERVER_BUFFER { TCHAR Name[20]; } PRINT_SERVER_BUFFER;
typedef struct _PRINT_SERVER_LIST { ULONG Count; PRINT_SERVER_BUFFER PSList[]; } PRINT_SERVER_LIST;
/////////////////////////////////////////////////////////////////////////
int NWGetMaxServerNameLen()
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ return MAX_SERVER_NAME_LEN;
} // NWGetMaxServerNameLen
/////////////////////////////////////////////////////////////////////////
int NWGetMaxUserNameLen()
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ return MAX_USER_NAME_LEN;
} // NWGetMaxUserNameLen
/////////////////////////////////////////////////////////////////////////
DWORD NWServerFree()
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
if (CachedConn) NWDetachFromFileServer(CachedConn);
CachedConn = 0;
return (0);
} // NWServerFree
/////////////////////////////////////////////////////////////////////////
DWORD NWServerSet( LPTSTR FileServer )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ NWLOCAL_SCOPE ScopeFlag = 0; NWCONN_HANDLE Conn = 0; NWCCODE ret = 0; char szAnsiFileServer[MAX_SERVER_NAME_LEN + 1];
NWServerFree();
lstrcpy(CachedServer, FileServer); CharToOem(FileServer, szAnsiFileServer);
ret = NWAttachToFileServer(szAnsiFileServer, ScopeFlag, &Conn);
if (!ret) { CachedConn = Conn; NWServerTimeGet(); }
return ((DWORD) ret);
} // NWServerSet
/////////////////////////////////////////////////////////////////////////
VOID NWUseDel( LPTSTR ServerName )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static TCHAR LocServer[MAX_SERVER_NAME_LEN+3];
NWServerFree(); wsprintf(LocServer, Lids(IDS_S_27), ServerName); WNetCancelConnection2(LocServer, 0, FALSE);
} // NWUseDel
/////////////////////////////////////////////////////////////////////////
BOOL NWUserNameValidate( LPTSTR szUserName )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ TCHAR UserName[MAX_USER_NAME_LEN + 1]; DWORD Size;
// if same as logged on user then don't convert or overwrite
Size = sizeof(UserName); WNetGetUser(NULL, UserName, &Size); if (!lstrcmpi(szUserName, UserName)) return FALSE;
// Now check for other special names
if (!lstrcmpi(szUserName, Lids(IDS_S_28))) return FALSE;
if (!lstrcmpi(szUserName, Lids(IDS_S_29))) return FALSE;
if (!lstrcmpi(szUserName, Lids(IDS_S_30))) return FALSE;
return TRUE;
} // NWUserNameValidate
/////////////////////////////////////////////////////////////////////////
BOOL NWGroupNameValidate( LPTSTR szGroupName )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
if (!lstrcmpi(szGroupName, Lids(IDS_S_31))) return FALSE;
if (!lstrcmpi(szGroupName, Lids(IDS_S_28))) return FALSE;
return TRUE;
} // NWGroupNameValidate
/////////////////////////////////////////////////////////////////////////
LPTSTR NWSpecialNamesMap( LPTSTR Name )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG i; static BOOL InitStrings = FALSE; static LPTSTR SpecialNames[5]; static LPTSTR SpecialMap[5];
if (!InitStrings) { InitStrings = TRUE; SpecialNames[0] = Lids(IDS_S_28); SpecialNames[1] = Lids(IDS_S_30); SpecialNames[2] = Lids(IDS_S_31); SpecialNames[3] = Lids(IDS_S_29); SpecialNames[4] = NULL;
SpecialMap[0] = Lids(IDS_S_32); SpecialMap[1] = Lids(IDS_S_32); SpecialMap[2] = Lids(IDS_S_33); SpecialMap[3] = Lids(IDS_S_29); SpecialMap[4] = NULL; }
i = 0; while(SpecialNames[i] != NULL) { if (!lstrcmpi(SpecialNames[i], Name)) { return SpecialMap[i]; }
i++; }
return Name;
} // NWSpecialNamesMap
/////////////////////////////////////////////////////////////////////////
BOOL NWIsAdmin( LPTSTR UserName )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ char szAnsiUserName[MAX_USER_NAME_LEN]; NWCCODE ret;
CharToOem(UserName, szAnsiUserName); ret = NWIsObjectInSet(CachedConn, szAnsiUserName, OT_USER, SECURITY_EQUALS, SUPERVISOR, OT_USER);
if (ret == SUCCESSFUL) return TRUE; else return FALSE;
} // NWIsAdmin
/////////////////////////////////////////////////////////////////////////
BOOL NWObjectNameGet( DWORD ObjectID, LPTSTR ObjectName )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ char szAnsiObjectName[MAX_USER_NAME_LEN + 1]; WORD wFoundUserType = 0; NWCCODE ret;
lstrcpy(ObjectName, TEXT(""));
if (!(ret = NWGetObjectName(CachedConn, ObjectID, szAnsiObjectName, &wFoundUserType))) {
//
// Got user - now convert and save off the information
//
OemToChar(szAnsiObjectName, ObjectName); }
if (ret == SUCCESSFUL) return TRUE; else return FALSE;
} // NWObjectNameGet
#define DEF_NUM_RECS 200
/////////////////////////////////////////////////////////////////////////
DWORD NWUsersEnum( USER_LIST **lpUsers, BOOL Display )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ USER_LIST *Users = NULL; USER_BUFFER *UserBuffer = NULL; DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
DWORD Count = 0; DWORD status = 0; char szAnsiUserName[MAX_USER_NAME_LEN + 1]; TCHAR szUserName[MAX_USER_NAME_LEN + 1]; WORD wFoundUserType = 0; DWORD dwObjectID = 0xFFFFFFFFL; BYTE byPropertiesFlag = 0; BYTE byObjectFlag = 0; BYTE byObjectSecurity = 0; NWCCODE ret;
if (Display) Status_ItemLabel(Lids(IDS_S_44));
Users = (USER_LIST *) AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; } else { UserBuffer = Users->UserBuffer;
// init to NULL so doesn't have garbage if call fails
lstrcpyA(szAnsiUserName, "");
// Loop through bindery getting all the users.
while ((ret = NWScanObject(CachedConn, "*", OT_USER, &dwObjectID, szAnsiUserName, &wFoundUserType, &byPropertiesFlag, &byObjectFlag, &byObjectSecurity)) == SUCCESSFUL) {
// Got user - now convert and save off the information
OemToChar(szAnsiUserName, szUserName);
if (NWUserNameValidate(szUserName)) { if (Display) Status_Item(szUserName);
lstrcpy(UserBuffer[Count].Name, szUserName); lstrcpy(UserBuffer[Count].NewName, szUserName); Count++; }
// Check if we have to re-allocate buffer
if (Count >= NumRecs) { NumRecs += DEF_NUM_RECS; Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; break; }
UserBuffer = Users->UserBuffer; }
}
// Gotta clear this out from the last loop
if (Count) ret = 0;
}
// check if error occured...
if (ret) status = ret;
// Now slim down the list to just what we need.
if (!status) { Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER)* Count));
if (!Users) status = ERROR_NOT_ENOUGH_MEMORY; else { // Sort the server list before putting it in the dialog
UserBuffer = Users->UserBuffer; qsort((void *) UserBuffer, (size_t) Count, sizeof(USER_BUFFER), UserListCompare); } }
if (Users != NULL) Users->Count = Count;
*lpUsers = Users;
return status;
} // NWUsersEnum
/////////////////////////////////////////////////////////////////////////
DWORD NWGroupsEnum( GROUP_LIST **lpGroups, BOOL Display )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ GROUP_LIST *Groups = NULL; GROUP_BUFFER *GroupBuffer; DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
DWORD Count = 0; DWORD status = 0; char szAnsiGroupName[MAX_GROUP_NAME_LEN + 1]; TCHAR szGroupName[MAX_GROUP_NAME_LEN + 1]; WORD wFoundGroupType = 0; DWORD dwObjectID = 0xFFFFFFFFL; BYTE byPropertiesFlag = 0; BYTE byObjectFlag = 0; BYTE byObjectSecurity = 0; NWCCODE ret;
if (Display) Status_ItemLabel(Lids(IDS_S_45));
Groups = (GROUP_LIST *) AllocMemory(sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * NumRecs));
if (!Groups) { status = ERROR_NOT_ENOUGH_MEMORY; } else { GroupBuffer = Groups->GroupBuffer;
// init to NULL so doesn't have garbage if call fails
lstrcpyA(szAnsiGroupName, "");
// Loop through bindery getting all the users.
while ((ret = NWScanObject(CachedConn, "*", OT_USER_GROUP, &dwObjectID, szAnsiGroupName, &wFoundGroupType, &byPropertiesFlag, &byObjectFlag, &byObjectSecurity)) == SUCCESSFUL) {
// Got user - now convert and save off the information
OemToChar(szAnsiGroupName, szGroupName);
if (NWGroupNameValidate(szGroupName)) { if (Display) Status_Item(szGroupName);
lstrcpy(GroupBuffer[Count].Name, szGroupName); lstrcpy(GroupBuffer[Count].NewName, szGroupName); Count++; }
// Check if we have to re-allocate buffer
if (Count >= NumRecs) { NumRecs += DEF_NUM_RECS; Groups = (GROUP_LIST *) ReallocMemory((HGLOBAL) Groups, sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * NumRecs));
if (!Groups) { status = ERROR_NOT_ENOUGH_MEMORY; break; }
GroupBuffer = Groups->GroupBuffer; }
}
// Gotta clear this out from the last loop
if (Count) ret = 0;
}
// check if error occured...
if (ret) status = ret;
// Now slim down the list to just what we need.
if (!status) { Groups = (GROUP_LIST *) ReallocMemory((HGLOBAL) Groups, sizeof(GROUP_LIST) + (sizeof(GROUP_BUFFER) * Count));
if (!Groups) status = ERROR_NOT_ENOUGH_MEMORY; else { // Sort the server list before putting it in the dialog
GroupBuffer = Groups->GroupBuffer; qsort((void *) GroupBuffer, (size_t) Count, sizeof(GROUP_BUFFER), UserListCompare); } }
if (Groups != NULL) Groups->Count = Count;
*lpGroups = Groups;
return status;
} // NWGroupsEnum
/////////////////////////////////////////////////////////////////////////
DWORD NWGroupUsersEnum( LPTSTR GroupName, USER_LIST **lpUsers )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ USER_LIST *Users = NULL; USER_BUFFER *UserBuffer; DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
DWORD Count = 0; DWORD i = 0; DWORD status = 0; char szAnsiUserName[MAX_USER_NAME_LEN + 1]; char szAnsiGroupName[MAX_GROUP_NAME_LEN + 1]; TCHAR szUserName[MAX_USER_NAME_LEN + 1]; WORD wFoundUserType = 0; BYTE byPropertyFlags = 0; BYTE byObjectFlag = 0; BYTE byObjectSecurity = 0; UCHAR Segment = 1; DWORD bySegment[32]; BYTE byMoreSegments; NWCCODE ret;
Users = (USER_LIST *) AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; } else { UserBuffer = Users->UserBuffer;
// init to NULL so doesn't have garbage if call fails
lstrcpyA(szAnsiUserName, ""); CharToOem(GroupName, szAnsiGroupName);
// Loop through bindery getting all the users.
do { if (!(ret = NWReadPropertyValue(CachedConn, szAnsiGroupName, OT_USER_GROUP, GROUP_MEMBERS, Segment, (BYTE *) bySegment, &byMoreSegments, &byPropertyFlags))) {
Segment++; // loop through properties converting them to user names
i = 0; while ((bySegment[i]) && (i < 32)) { if (!(ret = NWGetObjectName(CachedConn, bySegment[i], szAnsiUserName, &wFoundUserType))) { // Got user - now convert and save off the information
OemToChar(szAnsiUserName, szUserName);
lstrcpy(UserBuffer[Count].Name, szUserName); lstrcpy(UserBuffer[Count].NewName, szUserName); Count++;
// Check if we have to re-allocate buffer
if (Count >= NumRecs) { NumRecs += DEF_NUM_RECS; Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs)); if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; break; }
UserBuffer = Users->UserBuffer; } } i++; }
} else // if NWReadPropertyValue
byMoreSegments = 0;
} while (byMoreSegments);
// Gotta clear this out from the last loop
if (Count) ret = 0;
}
// check if error occured...
if (ret) status = ret;
// Now slim down the list to just what we need.
if (!status) { Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * Count));
if (!Users) status = ERROR_NOT_ENOUGH_MEMORY; else { // Sort the server list before putting it in the dialog
UserBuffer = Users->UserBuffer; qsort((void *) UserBuffer, (size_t) Count, sizeof(USER_BUFFER), UserListCompare); } }
if (Users != NULL) Users->Count = Count;
*lpUsers = Users;
return status;
} // NWGroupUsersEnum
/////////////////////////////////////////////////////////////////////////
DWORD NWUserEquivalenceEnum( LPTSTR UserName, USER_LIST **lpUsers )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ USER_LIST *Users; USER_BUFFER *UserBuffer; DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
DWORD Count = 0; DWORD i = 0; DWORD status = 0; char szAnsiUserName[MAX_USER_NAME_LEN + 1]; char szAnsiName[MAX_GROUP_NAME_LEN + 1]; TCHAR szUserName[MAX_USER_NAME_LEN + 1]; WORD wFoundUserType = 0; DWORD dwObjectID = 0xFFFFFFFFL; BYTE byPropertyFlags = 0; BYTE byObjectFlag = 0; BYTE byObjectSecurity = 0; UCHAR Segment = 1; DWORD bySegment[32]; BYTE byMoreSegments; NWCCODE ret;
Users = (USER_LIST *) AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; } else { UserBuffer = Users->UserBuffer;
// init to NULL so doesn't have garbage if call fails
lstrcpyA(szAnsiUserName, ""); CharToOem(UserName, szAnsiName);
// Loop through bindery getting all the users.
do { if (!(ret = NWReadPropertyValue(CachedConn, szAnsiName, OT_USER, SECURITY_EQUALS, Segment, (BYTE *) bySegment, &byMoreSegments, &byPropertyFlags))) {
Segment++; // loop through properties converting them to user names
i = 0; while ((bySegment[i]) && (i < 32)) { if (!(ret = NWGetObjectName(CachedConn, bySegment[i], szAnsiUserName, &wFoundUserType))) { // Got user - now convert and save off the information
OemToChar(szAnsiUserName, szUserName);
// Map out Everyone equivalence
if (lstrcmpi(szUserName, Lids(IDS_S_31))) { lstrcpy(UserBuffer[Count].Name, szUserName); lstrcpy(UserBuffer[Count].NewName, szUserName); Count++; }
// Check if we have to re-allocate buffer
if (Count >= NumRecs) { NumRecs += DEF_NUM_RECS; Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs)); if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; break; }
UserBuffer = Users->UserBuffer; } } i++; }
} else // if NWReadPropertyValue
byMoreSegments = 0;
} while (byMoreSegments);
// Gotta clear this out from the last loop
if (Count) ret = 0;
}
// check if error occured...
if (ret) status = ret;
// Now slim down the list to just what we need.
if (!status) { Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * Count));
if (!Users) status = ERROR_NOT_ENOUGH_MEMORY; else { // Sort the server list before putting it in the dialog
UserBuffer = Users->UserBuffer; qsort((void *) UserBuffer, (size_t) Count, sizeof(USER_BUFFER), UserListCompare); } }
if (Users != NULL) Users->Count = Count;
*lpUsers = Users;
return status;
} // NWUserEquivalenceEnum
/////////////////////////////////////////////////////////////////////////
DWORD NWFileRightsEnum( LPTSTR FileName, USER_RIGHTS_LIST **lpUsers, DWORD *UserCount, BOOL DownLevel )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ BOOL Continue = TRUE; USER_RIGHTS_LIST *Users = NULL; DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
DWORD Count = 0; DWORD i = 0; DWORD status = 0; char szAnsiUserName[MAX_USER_NAME_LEN + 1]; char szAnsiSearchDir[MAX_PATH + 1]; TCHAR szUserName[MAX_USER_NAME_LEN + 1]; WORD wFoundUserType = 0; NWCCODE ret; char FoundDir[16]; ULONG Entries;
TRUSTEE_INFO ti[20]; BYTE DirHandle, nDirHandle; BYTE Sequence; BYTE NumEntries = 0; NWDATE_TIME dtime = 0; NWOBJ_ID ownerID = 0;
if (DownLevel) { Entries = 5; Sequence = 1; } else { Entries = 20; Sequence = 0; }
DirHandle = nDirHandle = 0; memset(ti, 0, sizeof(ti));
Users = (USER_RIGHTS_LIST *) AllocMemory(NumRecs * sizeof(USER_RIGHTS_LIST));
if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; } else {
// init to NULL so doesn't have garbage if call fails
lstrcpyA(szAnsiUserName, ""); CharToOem(FileName, szAnsiSearchDir);
// Loop through bindery getting all the users.
do { if (DownLevel) ret = NWCScanDirectoryForTrustees2(CachedConn, nDirHandle, szAnsiSearchDir, &Sequence, FoundDir, &dtime, &ownerID, ti); else ret = NWCScanForTrustees(CachedConn, nDirHandle, szAnsiSearchDir, &Sequence, &NumEntries, ti);
if (!ret) { // loop through properties converting them to user names
for (i = 0; i < Entries; i++) { if (ti[i].objectID != 0) { if (!(ret = NWGetObjectName(CachedConn, ti[i].objectID, szAnsiUserName, &wFoundUserType))) { // Got user - now convert and save off the information
OemToChar(szAnsiUserName, szUserName);
lstrcpy(Users[Count].Name, szUserName); Users[Count].Rights = ti[i].objectRights; Count++;
// Check if we have to re-allocate buffer
if (Count >= NumRecs) { NumRecs += DEF_NUM_RECS; Users = (USER_RIGHTS_LIST *) ReallocMemory((HGLOBAL) Users, NumRecs * sizeof(USER_RIGHTS_LIST)); if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; break; } } // if realloc buffer
} } // if objectID != 0
}
} else // NWScan failed
Continue = FALSE;
} while (Continue);
// Gotta clear this out from the last loop
if (Count) ret = 0;
}
// check if error occured...
if (ret) { status = ret;
if (Users != NULL) { FreeMemory(Users); Count = 0; } }
// Now slim down the list to just what we need.
if (!status) { Users = (USER_RIGHTS_LIST *) ReallocMemory((HGLOBAL) Users, Count * sizeof(USER_RIGHTS_LIST));
if (!Users) status = ERROR_NOT_ENOUGH_MEMORY; else // Sort the server list before putting it in the dialog
qsort((void *) Users, (size_t) Count, sizeof(USER_RIGHTS_LIST), UserListCompare); }
*UserCount = Count; *lpUsers = Users;
return status;
} // NWFileRightsEnum
/////////////////////////////////////////////////////////////////////////
VOID NWLoginTimesMap( BYTE *Times, BYTE *NewTimes )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ DWORD i, j; int Bit = 0; int Val; BYTE BitSet;
for (i = 0; i < 21; i++) { BitSet = 0;
for (j = 0; j < 8; j++) { if (BitTest(Bit, Times) || BitTest(Bit+1, Times)) { Val = 0x1 << j; BitSet = BitSet + (BYTE) Val; }
Bit++; Bit++; }
NewTimes[i] = BitSet; }
} // NWLoginTimesMap
/*+-------------------------------------------------------------------------+
| Time Conversion | +-------------------------------------------------------------------------+*/
#define IS_LEAP(y) ((y % 4 == 0) && (y % 100 != 0 || y % 400 == 0))
#define DAYS_IN_YEAR(y) (IS_LEAP(y) ? 366 : 365)
#define DAYS_IN_MONTH(m,y) (IS_LEAP(y) ? _days_month_leap[m] : _days_month[m])
#define SECS_IN_DAY (60L * 60L * 24L)
#define SECS_IN_HOUR (60L * 60L)
#define SECS_IN_MINUTE (60L)
static short _days_month_leap[] = { 31,29,31,30,31,30,31,31,30,31,30,31 }; static short _days_month[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
/////////////////////////////////////////////////////////////////////////
BOOL NWTimeMap( DWORD Days, DWORD dwMonth, DWORD dwYear, DWORD dwBasis, ULONG *Time )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ DWORD dw = 0; DWORD dwDays = 0;
// Zero
*Time = 0L;
// Adjust year
if(dwYear < 70) dwYear += 2000L; else if(dwYear < 100) dwYear += 1900L;
if (dwYear < dwBasis) return FALSE;
// Calculate days in previous years, take -1 so we skip current year
dw = dwYear - 1; while(dw >= dwBasis) { dwDays += DAYS_IN_YEAR(dw); --dw; }
// Days from month
if((dwMonth < 1)||(dwMonth > 12)) return FALSE;
// Loop through adding number of days in each month. Take -2 (-1 to skip
// current month, and -1 to make 0 based).
dw = dwMonth; while(dw > 1) { dwDays += DAYS_IN_MONTH(dw-2, dwYear); --dw; }
// Convert days
dw = Days; if((dw >= 1) && (dw <= (DWORD) DAYS_IN_MONTH(dwMonth - 1, dwYear))) dwDays += dw; else return FALSE; // out of range
*Time += dwDays * SECS_IN_DAY; return TRUE; } // NWTimeMap
/////////////////////////////////////////////////////////////////////////
LPTSTR NWUserNameGet( LPTSTR szUserName )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static TCHAR UserName[128]; char szAnsiUserName[MAX_USER_NAME_LEN]; NWCCODE ret; BYTE bySegment[128]; BYTE byMoreSegments, byPropertyFlags; LPSTR szAnsiFullName;
CharToOem(szUserName, szAnsiUserName); ret = NWReadPropertyValue(CachedConn, szAnsiUserName, OT_USER, IDENTIFICATION, 1, bySegment, &byMoreSegments, &byPropertyFlags);
if (ret == SUCCESSFUL) { szAnsiFullName = (LPSTR) bySegment; OemToChar(szAnsiFullName, UserName); return UserName; }
return NULL;
} // NWUserNameGet
/////////////////////////////////////////////////////////////////////////
VOID NWNetUserMapInfo ( LPTSTR szUserName, VOID *UInfo, NT_USER_INFO *NT_UInfo )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG expires; struct tagLoginControl *tag; LPTSTR FullName;
tag = (struct tagLoginControl *) UInfo;
FullName = NWUserNameGet(szUserName); if (FullName != NULL) lstrcpyn(NT_UInfo->full_name, FullName, MAXCOMMENTSZ);
// Account disabled
if (tag->byAccountDisabled) NT_UInfo->flags = NT_UInfo->flags | 0x02;
// account locked out
if ((tag->wBadLogins == 0xffff) && (tag->lNextResetTime > (LONG)CachedServerTime)) NT_UInfo->flags = NT_UInfo->flags | 0x02; // disable account...
// user can change password
if ((tag->byRestrictions & 0x01)) NT_UInfo->flags = NT_UInfo->flags | 0x40;
NWLoginTimesMap(tag->byLoginTimes, NT_UInfo->logon_hours);
// account expires
if (tag->byAccountExpires[0] == 0) NT_UInfo->acct_expires = TIMEQ_FOREVER; else if (tag->byAccountExpires[0] < 70) NT_UInfo->acct_expires = 0; else { // fits within time range so convert to #seconds since 1970
expires = 0; NWTimeMap((DWORD) tag->byAccountExpires[2], (DWORD) tag->byAccountExpires[1], (DWORD) tag->byAccountExpires[0], 1970, &expires); NT_UInfo->acct_expires = expires; }
} // NWNetUserMapInfo
/////////////////////////////////////////////////////////////////////////
VOID NWFPNWMapInfo( VOID *NWUInfo, PFPNW_INFO fpnw )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ struct tagLoginControl *tag;
tag = (struct tagLoginControl *) NWUInfo;
fpnw->MaxConnections = tag->wMaxConnections; fpnw->PasswordInterval = tag->wPasswordInterval; fpnw->GraceLoginAllowed = tag->byGraceLogins; fpnw->GraceLoginRemaining = tag->byGraceLoginReset; fpnw->LoginFrom = NULL; fpnw->HomeDir = NULL;
} // NWFPNWMapInfo
/////////////////////////////////////////////////////////////////////////
VOID NWUserDefaultsGet( VOID **UDefaults )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ struct tagUserDefaults *UserDefaults = NULL; NWCCODE ret; BYTE bySegment[128]; BYTE byMoreSegments, byPropertyFlags;
ret = NWReadPropertyValue(CachedConn, SUPERVISOR, OT_USER, USER_DEFAULTS, 1, bySegment, &byMoreSegments, &byPropertyFlags);
if (ret == SUCCESSFUL) { UserDefaults = AllocMemory(sizeof(struct tagUserDefaults)); memcpy(UserDefaults, bySegment, sizeof (struct tagUserDefaults));
// Now put the data in 'normal' Intel format
SWAPBYTES(UserDefaults->wPasswordInterval); SWAPBYTES(UserDefaults->wMaxConnections); SWAPWORDS(UserDefaults->lBalance); SWAPWORDS(UserDefaults->lCreditLimit); SWAPWORDS(UserDefaults->lMaxDiskBlocks); }
*UDefaults = (void *) UserDefaults;
} // NWUserDefaultsGet
/////////////////////////////////////////////////////////////////////////
VOID NWUserDefaultsMap( VOID *NWUDefaults, NT_DEFAULTS *NTDefaults )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ struct tagUserDefaults *UserDefaults = NULL;
if ((NWUDefaults == NULL) || (NTDefaults == NULL)) return;
UserDefaults = (struct tagUserDefaults *) NWUDefaults;
NTDefaults->min_passwd_len = (DWORD) UserDefaults->byMinPasswordLength; NTDefaults->max_passwd_age = (DWORD) UserDefaults->wPasswordInterval * 86400; NTDefaults->force_logoff = (DWORD) UserDefaults->byGraceLoginReset;
// These fields aren't used/converted
// NTDefaults->min-passwd_age - no such thing for NetWare
// NTDefaults->password_hist_len - no such thing for NetWare
} // NWUserDefaultsMap
/////////////////////////////////////////////////////////////////////////
VOID NWLoginTimesLog( BYTE *Times )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ TCHAR *szDays[7]; DWORD Day; DWORD Hours; int Bit = 0, i; static TCHAR szHours[80];
szDays[0] = Lids(IDS_SUN); szDays[1] = Lids(IDS_MON); szDays[2] = Lids(IDS_TUE); szDays[3] = Lids(IDS_WED); szDays[4] = Lids(IDS_THU); szDays[5] = Lids(IDS_FRI); szDays[6] = Lids(IDS_SAT);
LogWriteLog(1, Lids(IDS_CRLF)); LogWriteLog(1, Lids(IDS_L_104));
// while these should be level 2, there isn't room on 80 cols - so level 1
LogWriteLog(1, Lids(IDS_L_1)); LogWriteLog(1, Lids(IDS_L_2)); LogWriteLog(1, Lids(IDS_L_3));
for (Day = 0; Day < 7; Day++) { LogWriteLog(1, szDays[Day]); lstrcpy(szHours, TEXT(" "));
for (Hours = 0; Hours < 24; Hours++) { for (i = 0; i < 2; i++) { if (BitTest(Bit, Times)) lstrcat(szHours, TEXT("*")); else lstrcat(szHours, TEXT(" "));
Bit++; }
lstrcat(szHours, TEXT(" ")); }
LogWriteLog(0, szHours); LogWriteLog(0, Lids(IDS_CRLF)); }
LogWriteLog(0, Lids(IDS_CRLF));
} // NWLoginTimesLog
/////////////////////////////////////////////////////////////////////////
VOID NWUserDefaultsLog( VOID *UDefaults )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ struct tagUserDefaults *tag;
tag = (struct tagUserDefaults *) UDefaults;
// Account expires
LogWriteLog(1, Lids(IDS_L_109)); if (tag->byAccountExpiresYear == 0) LogWriteLog(0, Lids(IDS_L_107)); else LogWriteLog(0, TEXT("%02u/%02u/%04u"), (UINT) tag->byAccountExpiresDay, (UINT) tag->byAccountExpiresMonth, (UINT) 1900 + tag->byAccountExpiresYear);
LogWriteLog(0, Lids(IDS_CRLF));
// Restrictions
LogWriteLog(1, Lids(IDS_L_110)); // user can change password
if ((tag->byRestrictions & 0x01)) LogWriteLog(2, Lids(IDS_L_111)); else LogWriteLog(2, Lids(IDS_L_112));
// unique password required
if ((tag->byRestrictions & 0x02)) LogWriteLog(2, Lids(IDS_L_113), Lids(IDS_YES)); else LogWriteLog(2, Lids(IDS_L_113), Lids(IDS_NO));
// Password interval
LogWriteLog(1, Lids(IDS_L_114)); if (tag->wPasswordInterval == 0) LogWriteLog(0, Lids(IDS_L_107)); else LogWriteLog(0, TEXT("%u"), (UINT) tag->wPasswordInterval);
LogWriteLog(0, Lids(IDS_CRLF));
// Grace Logins
LogWriteLog(1, Lids(IDS_L_115)); if (tag->byGraceLoginReset == 0xff) LogWriteLog(0, Lids(IDS_L_108)); else LogWriteLog(0, TEXT("%u"), (UINT) tag->byGraceLoginReset);
LogWriteLog(0, Lids(IDS_CRLF));
LogWriteLog(1, Lids(IDS_L_116), (UINT) tag->byMinPasswordLength);
// Max Connections
LogWriteLog(1, Lids(IDS_L_117)); if (tag->wMaxConnections == 0) LogWriteLog(0, Lids(IDS_L_108)); else LogWriteLog(0, TEXT("%u"), (UINT) tag->wMaxConnections);
LogWriteLog(0, Lids(IDS_CRLF));
LogWriteLog(1, Lids(IDS_L_118), (ULONG) tag->lBalance); LogWriteLog(1, Lids(IDS_L_119), (ULONG) tag->lCreditLimit);
// Max Disk blocks
LogWriteLog(1, Lids(IDS_L_120)); if (tag->lMaxDiskBlocks == 0x7FFFFFFF) LogWriteLog(0, Lids(IDS_L_108)); else LogWriteLog(0, TEXT("%lu"), (ULONG) tag->lMaxDiskBlocks);
LogWriteLog(0, Lids(IDS_CRLF)); LogWriteLog(0, Lids(IDS_CRLF));
} // NWUserDefaultsLog
/////////////////////////////////////////////////////////////////////////
VOID NWUserInfoLog( LPTSTR szUserName, VOID *UInfo )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ struct tagLoginControl *tag; LPTSTR FullName;
tag = (struct tagLoginControl *) UInfo;
LogWriteLog(1, Lids(IDS_L_105));
// Full Name
LogWriteLog(2, Lids(IDS_L_106));
FullName = NWUserNameGet(szUserName); if (FullName != NULL) LogWriteLog(2, FullName); LogWriteLog(0, Lids(IDS_CRLF));
// Account disabled
if (tag->byAccountDisabled == 0xff) LogWriteLog(2, Lids(IDS_L_121), Lids(IDS_YES)); else if ((tag->wBadLogins == 0xffff) && (tag->lNextResetTime > (LONG)CachedServerTime)) LogWriteLog(2, Lids(IDS_L_121), Lids(IDS_LOCKED_OUT)); else LogWriteLog(2, Lids(IDS_L_121), Lids(IDS_NO));
// Account expires
LogWriteLog(2, Lids(IDS_L_109)); if (tag->byAccountExpires[0] == 0) LogWriteLog(0, Lids(IDS_L_107)); else LogWriteLog(0, TEXT("%02u/%02u/%04u"), (UINT) tag->byAccountExpires[1], (UINT) tag->byAccountExpires[2], (UINT) 1900 + tag->byAccountExpires[0]);
LogWriteLog(0, Lids(IDS_CRLF));
// Password Expires
LogWriteLog(2, Lids(IDS_L_122)); if (tag->byPasswordExpires[0] == 0) LogWriteLog(0, Lids(IDS_L_107)); else LogWriteLog(0, TEXT("%02u/%02u/19%02u"), (int) tag->byPasswordExpires[1], (int) tag->byPasswordExpires[2], (int) tag->byPasswordExpires[0]);
LogWriteLog(0, Lids(IDS_CRLF));
// Grace logins
LogWriteLog(2, Lids(IDS_L_123)); if (tag->byGraceLogins == 0xff) LogWriteLog(0, Lids(IDS_L_108)); else LogWriteLog(0, TEXT("%u"), (UINT) tag->byGraceLogins);
LogWriteLog(0, Lids(IDS_CRLF));
// initial grace logins
LogWriteLog(2, Lids(IDS_L_115)); if (tag->byGraceLoginReset == 0xff) LogWriteLog(0, Lids(IDS_L_108)); else LogWriteLog(0, TEXT("%u"), (UINT) tag->byGraceLoginReset);
LogWriteLog(0, Lids(IDS_CRLF));
// Min password length
LogWriteLog(2, Lids(IDS_L_116), (UINT) tag->byMinPasswordLength);
// Password expiration
LogWriteLog(2, Lids(IDS_L_114)); if (tag->wPasswordInterval == 0) LogWriteLog(0, Lids(IDS_L_107)); else LogWriteLog(0, TEXT("%u"), (UINT) tag->wPasswordInterval);
LogWriteLog(0, Lids(IDS_CRLF));
// Max connections
LogWriteLog(2, Lids(IDS_L_117)); if (tag->wMaxConnections == 0) LogWriteLog(0, Lids(IDS_L_108)); else LogWriteLog(0, TEXT("%u"), (UINT) tag->wMaxConnections);
LogWriteLog(0, Lids(IDS_CRLF));
// Restrictions
// user can change password
LogWriteLog(2, Lids(IDS_L_110)); if ((tag->byRestrictions & 0x01)) LogWriteLog(3, Lids(IDS_L_111)); else LogWriteLog(3, Lids(IDS_L_112));
// unique password required
if ((tag->byRestrictions & 0x02)) LogWriteLog(3, Lids(IDS_L_113), Lids(IDS_YES)); else LogWriteLog(3, Lids(IDS_L_113), Lids(IDS_NO));
LogWriteLog(2, Lids(IDS_L_124), (UINT) tag->wBadLogins);
// Max Disk Blocks
LogWriteLog(2, Lids(IDS_L_120)); if (tag->lMaxDiskBlocks == 0x7FFFFFFF) LogWriteLog(0, Lids(IDS_L_108)); else LogWriteLog(0, TEXT("%lX"), tag->lMaxDiskBlocks);
LogWriteLog(0, Lids(IDS_CRLF));
// Login Times
NWLoginTimesLog(tag->byLoginTimes);
} // NWUserInfoLog
/////////////////////////////////////////////////////////////////////////
VOID NWUserInfoGet( LPTSTR szUserName, VOID **UInfo )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static struct tagLoginControl xUI; struct tagLoginControl *UserInfo = NULL; char szAnsiUserName[MAX_USER_NAME_LEN]; NWCCODE ret; BYTE bySegment[128]; BYTE byMoreSegments, byPropertyFlags;
CharToOem(szUserName, szAnsiUserName); ret = NWReadPropertyValue(CachedConn, szAnsiUserName, OT_USER, LOGIN_CONTROL, 1, bySegment, &byMoreSegments, &byPropertyFlags);
if (ret == SUCCESSFUL) { UserInfo = &xUI; memset(UserInfo, 0, sizeof(struct tagLoginControl)); memcpy(UserInfo, bySegment, sizeof (struct tagLoginControl));
// Now put the data in 'normal' Intel format
SWAPBYTES(UserInfo->wPasswordInterval); SWAPBYTES(UserInfo->wMaxConnections); SWAPWORDS(UserInfo->lMaxDiskBlocks); SWAPBYTES(UserInfo->wBadLogins); SWAPWORDS(UserInfo->lNextResetTime); }
*UInfo = (void *) UserInfo;
} // NWUserInfoGet
/////////////////////////////////////////////////////////////////////////
DWORD NWServerEnum( LPTSTR Container, SERVER_BROWSE_LIST **lpServList )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ int NumBufs = 0; DWORD TotalEntries = 0; ENUM_REC *BufHead, *CurrBuf, *OldBuf; SERVER_BROWSE_LIST *ServList = NULL; SERVER_BROWSE_BUFFER *SList = NULL; DWORD status = 0; DWORD i, j; NETRESOURCE ResourceBuf;
// Container is ignored - NW is a flat network topology...
SetProvider(NW_PROVIDER, &ResourceBuf);
BufHead = CurrBuf = OldBuf = NULL; status = EnumBufferBuild(&BufHead, &NumBufs, ResourceBuf);
if (!status) { // We have 0 to xxx Enum recs each with a buffer sitting off of it. Now
// need to consolidate these into one global enum list...
if (NumBufs) { CurrBuf = BufHead;
// Figure out how many total entries there are
while (CurrBuf) { TotalEntries += CurrBuf->cEntries; CurrBuf = CurrBuf->next; }
CurrBuf = BufHead;
// Now create a Server List to hold all of these.
ServList = AllocMemory(sizeof(SERVER_BROWSE_LIST) + TotalEntries * sizeof(SERVER_BROWSE_BUFFER));
if (ServList == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; } else { ServList->Count = TotalEntries; SList = (SERVER_BROWSE_BUFFER *) &ServList->SList;
j = 0;
// Now loop through copying the data...
while (CurrBuf) { for(i = 0; i < CurrBuf->cEntries; i++) { if (CurrBuf->lpnr[i].lpRemoteName != NULL) if (CurrBuf->lpnr[i].lpRemoteName[0] == TEXT('\\') && CurrBuf->lpnr[i].lpRemoteName[1] == TEXT('\\')) lstrcpy(SList[j].Name, &CurrBuf->lpnr[i].lpRemoteName[2]); else lstrcpy(SList[j].Name, CurrBuf->lpnr[i].lpRemoteName); else lstrcpy(SList[j].Name, TEXT(""));
if (CurrBuf->lpnr[i].lpComment != NULL) lstrcpy(SList[j].Description, CurrBuf->lpnr[i].lpComment); else lstrcpy(SList[j].Description, TEXT(""));
SList[j].Container = FALSE; j++; }
OldBuf = CurrBuf; CurrBuf = CurrBuf->next;
// Free the old buffer
FreeMemory((HGLOBAL) OldBuf); } // while
} // else (ServList)
} // if (numbufs)
}
*lpServList = ServList; return status;
} // NWServerEnum
/////////////////////////////////////////////////////////////////////////
ULONG NWShareSizeGet( LPTSTR Share )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static TCHAR RootPath[MAX_PATH + 1]; DWORD sectorsPC, bytesPS, FreeClusters, Clusters; DWORD TotalSpace, FreeSpace;
TotalSpace = FreeSpace = 0;
wsprintf(RootPath, TEXT("\\\\%s\\%s\\"), CachedServer, Share); if (GetDiskFreeSpace(RootPath, §orsPC, &bytesPS, &FreeClusters, &Clusters)) { TotalSpace = Clusters * sectorsPC * bytesPS; FreeSpace = FreeClusters * sectorsPC * bytesPS; }
// total - free = approx allocated space (if multiple shares on drive then
// this doesn't take that into account, we just want an approximation...
return TotalSpace - FreeSpace;
} // NWShareSizeGet
/////////////////////////////////////////////////////////////////////////
DWORD NWSharesEnum( SHARE_LIST **lpShares )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ int NumBufs = 0; DWORD TotalEntries = 0; ENUM_REC *BufHead, *CurrBuf, *OldBuf; SHARE_LIST *ShareList = NULL; SHARE_BUFFER *SList = NULL; DWORD status; DWORD i, j; NETRESOURCE ResourceBuf;
// Setup NETRESOURCE data structure
SetProvider(NW_PROVIDER, &ResourceBuf);
ResourceBuf.lpRemoteName = CachedServer; ResourceBuf.dwUsage = RESOURCEUSAGE_CONTAINER; status = EnumBufferBuild(&BufHead, &NumBufs, ResourceBuf);
if (!status) { // We have 0 to xxx Enum recs each with a buffer sitting off of it. Now
// need to consolidate these into one global enum list...
if (NumBufs) { CurrBuf = BufHead;
// Figure out how many total entries there are
while (CurrBuf) { TotalEntries += CurrBuf->cEntries; CurrBuf = CurrBuf->next; }
CurrBuf = BufHead;
// Now create a Server List to hold all of these.
ShareList = (SHARE_LIST *) AllocMemory(sizeof(SHARE_LIST) + (TotalEntries * sizeof(SHARE_BUFFER)));
if (ShareList == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; } else { j = 0;
// Zero out everything and get pointer to list
memset(ShareList, 0, sizeof(SHARE_LIST) + (TotalEntries * sizeof(SHARE_BUFFER))); ShareList->Count = TotalEntries; SList = (SHARE_BUFFER *) &ShareList->SList;
// Now loop through copying the data...
while (CurrBuf) { for(i = 0; i < CurrBuf->cEntries; i++) { if (CurrBuf->lpnr[i].lpRemoteName != NULL) lstrcpy(SList[j].Name, ShareNameParse(CurrBuf->lpnr[i].lpRemoteName)); else lstrcpy(SList[j].Name, TEXT(""));
SList[j].Size = NWShareSizeGet(SList[j].Name); SList[j].Index = (USHORT) j; j++; }
OldBuf = CurrBuf; CurrBuf = CurrBuf->next;
// Free the old buffer
FreeMemory((HGLOBAL) OldBuf); } // while
} // else (ShareList)
} // if (numbufs)
}
*lpShares = ShareList; return status;
} // NWSharesEnum
/////////////////////////////////////////////////////////////////////////
VOID NWServerInfoReset( SOURCE_SERVER_BUFFER *SServ )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static VERSION_INFO NWInfo; NWCCODE ret = 0;
ret = NWGetFileServerVersionInfo(CachedConn, &NWInfo);
// BUGBUG: This API returns fail (8801) - but is actually succeding,
// just ignore error for right now as it really doesn't matter for the
// version info.
// if (ret == SUCCESSFUL) {
SServ->VerMaj = NWInfo.Version; SServ->VerMin = NWInfo.SubVersion; // }
} // NWServerInfoReset
/////////////////////////////////////////////////////////////////////////
VOID NWServerInfoSet( LPTSTR ServerName, SOURCE_SERVER_BUFFER *SServ )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static VERSION_INFO NWInfo; NWCCODE ret = 0;
CursorHourGlass(); lstrcpy(SServ->Name, ServerName); NWServerInfoReset(SServ);
// Fill in share list
NWSharesEnum(&SServ->ShareList);
#ifdef DEBUG
{ DWORD i;
dprintf(TEXT("Adding NW Server: %s\n"), SServ->Name); dprintf(TEXT(" Version: %u.%u\n"), (UINT) SServ->VerMaj, (UINT) SServ->VerMin); dprintf(TEXT(" Shares\n")); dprintf(TEXT(" +---------------------------------------+\n")); if (SServ->ShareList) { for (i = 0; i < SServ->ShareList->Count; i++) { dprintf(TEXT(" %-15s AllocSpace %lu\n"), SServ->ShareList->SList[i].Name, SServ->ShareList->SList[i].Size); } } else dprintf(TEXT(" <Serv List enum failed!!>\n"));
dprintf(TEXT("\n"));
} #endif
CursorNormal();
} // NWServerInfoSet
/////////////////////////////////////////////////////////////////////////
BOOL NWServerValidate( HWND hWnd, LPTSTR ServerName, BOOL DupFlag )
/*++
Routine Description:
Validates a given server - makes sure it can be connected to and that the user has admin privs on it.
Arguments:
Return Value:
--*/
{ DWORD Status; BOOL ret = FALSE; SOURCE_SERVER_BUFFER *SServ = NULL; DWORD dwObjectID = 0; DWORD Size; BYTE AccessLevel; TCHAR UserName[MAX_USER_NAME_LEN + 1]; static TCHAR LocServer[MAX_SERVER_NAME_LEN+3]; LPVOID lpMessageBuffer;
CursorHourGlass();
if (DupFlag) SServ = SServListFind(ServerName);
if (SServ == NULL) { // Get Current Logged On User
lstrcpy(UserName, TEXT("")); Size = sizeof(UserName); WNetGetUser(NULL, UserName, &Size);
lstrcpy(LocServer, TEXT("\\\\")); lstrcat(LocServer, ServerName);
if (UseAddPswd(hWnd, UserName, LocServer, Lids(IDS_S_6), NW_PROVIDER)) {
Status = NWServerSet(ServerName);
if (Status) {
if (GetLastError() != 0) WarningError(Lids(IDS_NWCANT_CON), ServerName);
} else { if (IsNCPServerFPNW(CachedConn)) WarningError(Lids(IDS_E_18), ServerName); else { Status = NWCGetBinderyAccessLevel(CachedConn, &AccessLevel, &dwObjectID);
if (!Status) { AccessLevel &= BS_SUPER_READ; if (AccessLevel == BS_SUPER_READ) ret = TRUE; else WarningError(Lids(IDS_NWNO_ADMIN), ServerName); } } } } else { FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, (LPTSTR) &lpMessageBuffer, 0, NULL );
if (GetLastError() != 0) WarningError(Lids(IDS_E_9), ServerName, lpMessageBuffer);
LocalFree(lpMessageBuffer); } } else { // Already in source server list - can't appear more then once
WarningError(Lids(IDS_E_14), ServerName); }
CursorNormal(); return ret;
} // NWServerValidate
/////////////////////////////////////////////////////////////////////////
LPTSTR NWRightsLog( DWORD Rights )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static TCHAR NWRights[15]; lstrcpy(NWRights, Lids(IDS_S_34));
// Read
if (!(Rights & 0x01)) NWRights[2] = TEXT(' ');
// Write
if (!(Rights & 0x02)) NWRights[3] = TEXT(' ');
// Create
if (!(Rights & 0x08)) NWRights[4] = TEXT(' ');
// Delete (Erase)
if (!(Rights & 0x10)) NWRights[5] = TEXT(' ');
// Parental
if (!(Rights & 0x20)) NWRights[8] = TEXT(' ');
// Search
if (!(Rights & 0x40)) NWRights[7] = TEXT(' ');
// Modify
if (!(Rights & 0x80)) NWRights[6] = TEXT(' ');
// Supervisor (all rights set)
if ((Rights & 0xFB) != 0xFB) NWRights[1] = TEXT(' ');
return NWRights;
} // NWRightsLog
/////////////////////////////////////////////////////////////////////////
NTSTATUS MapNwRightsToNTAccess( ULONG NWRights, PRIGHTS_MAPPING pMap, ACCESS_MASK *pAccessMask )
/*++
Routine Description:
Map a NW Right to the appropriate NT AccessMask
Arguments:
NWRights - Netware rights we wish to map pMap - pointer to structure that defines the mapping
Return Value:
The NT AccessMask corresponding to the NW Rights
--*/
{ PNW_TO_NT_MAPPING pNWToNtMap = pMap->Nw2NtMapping ; ACCESS_MASK AccessMask = 0 ;
if (!pAccessMask) return STATUS_INVALID_PARAMETER ;
*pAccessMask = 0x0 ;
// go thru the mapping structuring, OR-ing in bits along the way
while (pNWToNtMap->NWRight) {
if (pNWToNtMap->NWRight & NWRights) AccessMask |= pNWToNtMap->NTAccess ;
pNWToNtMap++ ; }
*pAccessMask = AccessMask ;
return STATUS_SUCCESS ; } // MapNwRightsToNTAccess
/////////////////////////////////////////////////////////////////////////
DWORD NWPrintServersEnum( PRINT_SERVER_LIST **PS )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ PRINT_SERVER_LIST *psl; PRINT_SERVER_BUFFER *pbuff; DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
DWORD Count = 0; DWORD status = 0; char szAnsiPrinterName[MAX_USER_NAME_LEN + 1]; TCHAR szPrinterName[MAX_USER_NAME_LEN + 1]; WORD wFoundUserType = 0; DWORD dwObjectID = 0xFFFFFFFFL; BYTE byPropertiesFlag = 0; BYTE byObjectFlag = 0; BYTE byObjectSecurity = 0; NWCCODE ret;
psl = (PRINT_SERVER_LIST *) AllocMemory(sizeof(PRINT_SERVER_LIST) + (NumRecs * sizeof(PRINT_SERVER_BUFFER)));
if (!psl) { status = ERROR_NOT_ENOUGH_MEMORY; } else { pbuff = psl->PSList;
// init to NULL so doesn't have garbage if call fails
lstrcpyA(szAnsiPrinterName, "");
// Loop through bindery getting all the users.
while ((ret = NWScanObject(CachedConn, "*", OT_PRINT_SERVER, &dwObjectID, szAnsiPrinterName, &wFoundUserType, &byPropertiesFlag, &byObjectFlag, &byObjectSecurity)) == SUCCESSFUL) {
// Got user - now convert and save off the information
OemToChar(szAnsiPrinterName, szPrinterName);
lstrcpy(pbuff[Count].Name, szPrinterName); Count++;
// Check if we have to re-allocate buffer
if (Count >= NumRecs) { NumRecs += DEF_NUM_RECS; psl = (PRINT_SERVER_LIST *) ReallocMemory((HGLOBAL) psl, sizeof(PRINT_SERVER_LIST) + (NumRecs * sizeof(PRINT_SERVER_BUFFER))); pbuff = psl->PSList;
if (!psl) { status = ERROR_NOT_ENOUGH_MEMORY; break; }
}
}
// Gotta clear this out from the last loop
if (Count) ret = 0;
}
// check if error occured...
if (ret) status = ret;
// Now slim down the list to just what we need.
if (!status) { psl = (PRINT_SERVER_LIST *) ReallocMemory((HGLOBAL) psl, sizeof(PRINT_SERVER_LIST) + (Count * sizeof(PRINT_SERVER_BUFFER)));
if (!psl) status = ERROR_NOT_ENOUGH_MEMORY; }
psl->Count = Count; *PS = psl;
return status;
} // NWPrintServersEnum
/////////////////////////////////////////////////////////////////////////
DWORD NWPrintOpsEnum( USER_LIST **lpUsers )
/*++
Routine Description:
First need to enumerate all the print servers on the NetWare system we are pointing to. Next loop through each of these print servers and enumerate the print operators on each of them.
Arguments:
Return Value:
--*/
{ PRINT_SERVER_LIST *psl = NULL; PRINT_SERVER_BUFFER *PSList; ULONG pCount; USER_LIST *Users = NULL; USER_BUFFER *UserBuffer; DWORD NumRecs = DEF_NUM_RECS; // Default 200 names
DWORD Count = 0; DWORD ipsl = 0, iseg = 0; DWORD status = 0; char szAnsiUserName[MAX_USER_NAME_LEN + 1]; char szAnsiName[MAX_GROUP_NAME_LEN + 1]; TCHAR szUserName[MAX_USER_NAME_LEN + 1]; WORD wFoundUserType = 0; DWORD dwObjectID = 0xFFFFFFFFL; BYTE byPropertyFlags = 0; BYTE byObjectFlag = 0; BYTE byObjectSecurity = 0; UCHAR Segment = 1; DWORD bySegment[32]; BYTE byMoreSegments; NWCCODE ret;
*lpUsers = NULL;
// Enumerate the print servers - if there are none, then there are no printer ops
NWPrintServersEnum(&psl); if ((psl == NULL) || (psl->Count == 0)) { if (psl != NULL) FreeMemory(psl);
return 0; }
// Got some servers - loop through them enumerating users
Users = (USER_LIST *) AllocMemory(sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs));
if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; } else { UserBuffer = Users->UserBuffer; PSList = psl->PSList;
for (pCount = 0; pCount < psl->Count; pCount++) { // init to NULL so doesn't have garbage if call fails
lstrcpyA(szAnsiUserName, ""); CharToOem(PSList[ipsl++].Name, szAnsiName);
// Loop through bindery getting all the users.
do { if (!(ret = NWReadPropertyValue(CachedConn, szAnsiName, OT_PRINT_SERVER, PS_OPERATORS, Segment, (BYTE *) bySegment, &byMoreSegments, &byPropertyFlags))) {
Segment++; // loop through properties converting them to user names
iseg = 0; while ((bySegment[iseg]) && (iseg < 32)) { if (!(ret = NWGetObjectName(CachedConn, bySegment[iseg], szAnsiUserName, &wFoundUserType))) { // Got user - now convert and save off the information
OemToChar(szAnsiUserName, szUserName);
// Map out Supervisor (already print-op privs)
if (lstrcmpi(szUserName, Lids(IDS_S_28))) { lstrcpy(UserBuffer[Count].Name, szUserName); lstrcpy(UserBuffer[Count].NewName, szUserName); Count++; }
// Check if we have to re-allocate buffer
if (Count >= NumRecs) { NumRecs += DEF_NUM_RECS; Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * NumRecs)); if (!Users) { status = ERROR_NOT_ENOUGH_MEMORY; break; }
UserBuffer = Users->UserBuffer; } } iseg++; }
} else // if NWReadPropertyValue
byMoreSegments = 0;
} while (byMoreSegments);
// Gotta clear this out from the last loop
if (Count) ret = 0; } }
// check if error occured...
if (ret) status = ret;
// Now slim down the list to just what we need.
if (!status) { Users = (USER_LIST *) ReallocMemory((HGLOBAL) Users, sizeof(USER_LIST) + (sizeof(USER_BUFFER) * Count));
if (!Users) status = ERROR_NOT_ENOUGH_MEMORY; else { // Sort the server list before putting it in the dialog
UserBuffer = Users->UserBuffer; qsort((void *) UserBuffer, (size_t) Count, sizeof(USER_BUFFER), UserListCompare); } }
Users->Count = Count; *lpUsers = Users;
return status;
} // NWPrintOpsEnum
/////////////////////////////////////////////////////////////////////////
VOID NWServerTimeGet( )
/*++
Routine Description:
Queries server for it's current local time which is then converted to elasped minutes since 1985 in order to compare with the lNextResetTime field of the LOGIN_CONTROL structure (which must be byte-aligned).
Arguments:
None.
Return Value:
None.
--*/
{ DWORD dwYear = 0; DWORD dwMonth = 0; DWORD dwDay = 0; DWORD dwHour = 0; DWORD dwMinute = 0; DWORD dwSecond = 0; DWORD dwDayOfWeek = 0; DWORD dwServerTime = 0;
CachedServerTime = 0xffffffff; // re-initialize...
if (!NWGetFileServerDateAndTime( CachedConn, (LPBYTE)&dwYear, (LPBYTE)&dwMonth, (LPBYTE)&dwDay, (LPBYTE)&dwHour, (LPBYTE)&dwMinute, (LPBYTE)&dwSecond, (LPBYTE)&dwDayOfWeek)) { if (NWTimeMap(dwDay, dwMonth, dwYear, 1985, &dwServerTime)) { dwServerTime += dwHour * 3600; dwServerTime += dwMinute * 60; dwServerTime += dwSecond;
CachedServerTime = dwServerTime / 60; // convert to minutes...
} } }
/////////////////////////////////////////////////////////////////////////
BOOL IsNCPServerFPNW( NWCONN_HANDLE Conn )
/*++
Routine Description:
Check if this an FPNW server by checking for a specific object type and property.
Arguments:
Conn - connection id of ncp server.
Return Value:
Returns true if ncp server is fpnw.
--*/
{ NWCCODE ret; BYTE bySegment[128]; BYTE byMoreSegments, byPropertyFlags;
memset(bySegment, 0, sizeof(bySegment));
ret = NWReadPropertyValue( CachedConn, MS_EXTENDED_NCPS, 0x3B06, FPNW_PDC, 1, bySegment, &byMoreSegments, &byPropertyFlags );
return (ret == SUCCESSFUL) && (BOOL)(BYTE)bySegment[0]; }
|