home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Network Support Encyclopedia 96-1
/
novell-nsepro-1996-1-cd2.iso
/
download
/
netware
/
ndsvw.exe
/
NDSVIEW.C
next >
Wrap
Text File
|
1995-03-27
|
23KB
|
720 lines
/****************************************************************************
** File: NDSVIEW.C
**
** Desc: This program lists all of the attributes of all objects in
** a specific context in the tree. It is written as a snapin module for
** nwadmin so the currenly selected object in NWAdmin is the object
** used to display the attributes.
**
** After complilation, the snapin is installed by editing the nwadmin.ini
** file located in the c:\windows (or wherever installed) directory. The
** modification lookes something like this:
**
** [Snapin Object DLLs]
** NDSVIEW=D:\DEV\WIN\NDSVIEW\NDSVIEW.DLL
**
** where "D:\DEV\WIN\NDSVIEW" is the path to the dll to be loaded.
**
**
** DISCLAIMER
**
** Novell, Inc. makes no representations or warranties with respect to
** any NetWare software, and specifically disclaims any express or
** implied warranties of merchantability, title, or fitness for a
** particular purpose.
**
** Distribution of any NetWare software is forbidden without the
** express written consent of Novell, Inc. Further, Novell reserves
** the right to discontinue distribution of any NetWare software.
**
** Novell is not responsible for lost profits or revenue, loss of use
** of the software, loss of data, costs of re-creating lost data, the
** cost of any substitute equipment or program, or claims by any party
** other than you. Novell strongly recommends a backup be made before
** any software is installed. Technical support for this software
** may be provided at the discretion of Novell.
**
** History:
**
** When Who What
** -----------------------------------------------------------------------
** 10-20-94 CRG Original code adapted from dsview.c
** 03-27-95 CRG Cleaned up memory allocation.
*/
#define NWWIN
/***************************************************************************
** Libraries Linked in for .exe
**
** NWCALLS.LIB
** NWLOCALE.LIB
** NWNET.LIB
** SNAPIN.LIB
**
*/
/****************************************************************************
** Include headers, macros, function prototypes, etc.
*/
/*------------------------------------------------------------------------
** ANSI
*/
#include <windows.h>
#include <dos.h>
#include <io.h>
#include <toolhelp.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
/*------------------------------------------------------------------------
** NetWare
*/
#include <nwnet.h>
#include <nwsnapin.h>
#include "ndsview.h"
/*------------------------------------------------------------------------
** Prototypes
*/
BOOL FAR PASCAL _export NDSViewDlgProc(HWND hDlg, UINT message, UINT wParam,
LONG lParam);
N_EXTERN_LIBRARY( void ) NDSViewMenuAction(void);
N_EXTERN_LIBRARY( void ) NDSViewMenuValid(pnuint16 pFlags);
WORD InitDialogStuff(HWND hDlg);
WORD InitAttrListBox(HWND hDlg);
WORD UpdateValueListBox(HWND hDlg);
void DecodeRights(char *attrName, char *rightsstring, NWDS_PRIVILEGES privs);
long HandleCcode(HWND hDlg, NWDSCCODE ccode, char *procName);
/*------------------------------------------------------------------------
** Globals
*/
HINSTANCE hDLL;
char currObjName[MAX_DN_CHARS];
NWDSContextHandle gContext;
/***************************************************************************
** DLL Entry Point
*/
int FAR PASCAL LibMain (HINSTANCE hInstance, WORD wDataSeg,
WORD cbHeapSize, LPSTR lpCmdLine)
{
hDLL = hInstance;
if(cbHeapSize != 0)
UnlockData (0);
return 1;
};
/***************************************************************************
** Every Snapin DLL must provide this function. In this function,
** snapin menu items (under Tools) are registered. Also, object procs
** are registered.
*/
int _export FAR PASCAL InitSnapin()
{
nuint16 MenuIDNDSView=0;
/*-----------------------------------------------------------------------
** Registering Menu Item
*/
NWARegisterMenu(NWA_VIEW_BROWSER,
0,
NULL,
MF_STRING,
&MenuIDNDSView,
"View &Attributes",
"View Object's Attributes",
NDSViewMenuAction,
NDSViewMenuValid,
NWA_SNAPIN_VERSION);
return NWA_RET_SUCCESS;
}
/******************************************************************************
** Creates the main dialog for NDSView. Also sets up the Callback procedure
** NDSViewDlgProc to handle dialog messages.
*/
N_GLOBAL_LIBRARY( void ) _export
NDSViewMenuAction( void )
{
static FARPROC lpfnNDSViewDlgProc;
lpfnNDSViewDlgProc = MakeProcInstance((FARPROC)NDSViewDlgProc, hDLL);
DialogBox(hDLL, "NDSVIEW_DIALOG", GetActiveWindow(), lpfnNDSViewDlgProc);
FreeProcInstance(lpfnNDSViewDlgProc);
}
/******************************************************************************
** Validates the item under the tools menu in NWAdmin.
*/
N_GLOBAL_LIBRARY( void ) _export
NDSViewMenuValid( pnuint16 pFlags )
{
*pFlags=MF_ENABLED;
}
/******************************************************************************
** This is the callback procedure that handles the messages for the main
** dialog of the snapin.
*/
BOOL FAR PASCAL _export NDSViewDlgProc(HWND hDlg, UINT message, UINT wParam,
LONG lParam)
{
switch(message)
{
case WM_INITDIALOG:
InitDialogStuff(hDlg);
InitAttrListBox(hDlg);
SetFocus(GetDlgItem(hDlg, IDC_ATTR_NAMES));
return FALSE;
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE)
{
NWDSFreeContext(gContext);
EndDialog(hDlg, TRUE);
return TRUE;
}
case WM_COMMAND:
switch(wParam)
{
case BUT_QUIT:
NWDSFreeContext(gContext);
EndDialog(hDlg, TRUE);
return TRUE;
case IDC_ATTR_NAMES:
if (HIWORD (lParam) == LBN_SELCHANGE)
UpdateValueListBox(hDlg);
break;
default:
break;
}
break;
}
return FALSE;
}
/******************************************************************************
** Before the dialog windows is displayed, the values are initialized. This
** function creates the context and gets the currently selected object in
** NWAdmin and sets those values in the dialog window.
*/
WORD InitDialogStuff(HWND hDlg)
{
NWASelObject selObject;
NWDSCCODE ccode;
DWORD flags;
gContext = NWDSCreateContext();
if((int)gContext == ERR_CONTEXT_CREATION)
{
MessageBox(hDlg, "Create Context Failed with 'ERR_CONTEXT_CREATION'", "WDSVIEW Error", MB_OK);
return((WORD)gContext);
}
ccode = NWDSSetContext(gContext, DCK_NAME_CONTEXT, "[Root]");
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSSetContext");
return(ccode);
}
ccode = NWDSGetContext(gContext, DCK_FLAGS, &flags);
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSGetContext");
return(ccode);
}
/* Turning off Types for all names. (ie: is.novell not ou=is.o=novell) */
flags |= DCV_TYPELESS_NAMES;
flags &= ~DCV_CANONICALIZE_NAMES;
ccode = NWDSSetContext(gContext, DCK_FLAGS, &flags);
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSSetContext");
return(ccode);
}
NWAGetSelObject(0, &selObject);
strcpy(currObjName, selObject.objName);
SetDlgItemText(hDlg, IDC_OBJECT_NAME, currObjName);
return 0;
}
/***************************************************************************
** This is a generic error handling routine. It pops up a windows showing
** the message and error code passed in.
*/
long HandleCcode(HWND hDlg, NWDSCCODE ccode, char *procName)
{
char message[100];
sprintf(message,"%s returned code: 0x%X", procName, ccode);
MessageBox(hDlg, message, "WDSVIEW Error", MB_OK);
return 0;
};
/******************************************************************************
** This fills the attribute list for the currently selected object.
*/
WORD InitAttrListBox(HWND hDlg)
{
NWDS_BUFFER *outBuf;
NWDS_ITERATION iterationHandle = -1L;
NWDSCCODE ccode;
char attrName[MAX_DN_CHARS + 1];
NWCOUNT attrCount;
int i;
NWSYNTAX_ID syntax;
NWCOUNT valCount;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSAllocBuf");
return 1;
}
do
{
ccode = NWDSRead(
gContext, /* Context Handle (IN) */
currObjName, /* name of object (IN) */
DS_ATTRIBUTE_NAMES, /* a #define (IN) */
TRUE, /* #define as 1 (IN) */
NULL, /* Attribute names (IN) */
&iterationHandle, /* iteration Handle (OUT) */
outBuf); /* Output Buffer (OUT) */
if (ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSRead");
NWDSFreeBuf(outBuf);
return 1;
}
ccode = NWDSGetAttrCount(gContext, outBuf, &attrCount);
if (ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSGetAttrCount");
NWDSFreeBuf(outBuf);
return 1;
}
for(i = 0; i < attrCount; i++)
{
ccode = NWDSGetAttrName(gContext, outBuf, attrName, &valCount, &syntax);
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSGetAttrName");
NWDSFreeBuf(outBuf);
return 1;
}
SendDlgItemMessage(hDlg, IDC_ATTR_NAMES, LB_ADDSTRING, 0,
(LONG) (LPSTR) attrName);
}
}
while(iterationHandle != -1L);
NWDSFreeBuf(outBuf);
return 0;
}
/******************************************************************************
** Whenever a new attribute is selected, the value windows on the dialog
** must be updated with the new attributes value. This function does that.
*/
WORD UpdateValueListBox(HWND hDlg)
{
NWDS_BUFFER *outBuf,*inBuf;
NWDS_ITERATION iterationHandle;
NWDSCCODE ccode;
char attrName[MAX_DN_CHARS];
int j;
NWSIZE attrSize;
NWSYNTAX_ID syntax;
NWCOUNT valCount;
NWCOUNT totalAttrs;
char currAttr[MAX_DN_CHARS];
HANDLE htxtBuffer, htmpBuffer, hattrValue;
void *attrValue;
char *txtBuffer;
char *tmpBuffer;
char rightsstr[9];
struct date dt;
struct time tm;
WORD n;
int fHandle;
SetDlgItemText(hDlg, IDC_ATTR_VALUES, "");
n = (WORD) SendDlgItemMessage(hDlg, IDC_ATTR_NAMES, LB_GETCURSEL, 0, 0L);
SendDlgItemMessage(hDlg, IDC_ATTR_NAMES, LB_GETTEXT, n,
(LONG) (LPSTR) attrName);
strset(rightsstr, '\x0');
iterationHandle = -1L;
if((htxtBuffer = GlobalAlloc(LHND, DEFAULT_MESSAGE_LEN))==NULL)
{
MessageBox(hDlg, "Could not Allocate Memory", "Error", MB_OK);
return 1;
}
if((htmpBuffer = GlobalAlloc(LHND, DEFAULT_MESSAGE_LEN))==NULL)
{
GlobalFree(htxtBuffer);
MessageBox(hDlg, "Could not Allocate Memory", "Error", MB_OK);
return 1;
}
(void *)txtBuffer = GlobalLock(htxtBuffer);
(void *)tmpBuffer = GlobalLock(htmpBuffer);
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &inBuf);
if(ccode < 0)
{
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
HandleCcode(hDlg, ccode, "NWDSAllocBuf");
return(ccode);
}
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
if(ccode < 0)
{
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
HandleCcode(hDlg, ccode, "NWDSAllocBuf");
NWDSFreeBuf(inBuf);
return(ccode);
}
ccode = NWDSInitBuf(gContext,DSV_READ,inBuf);
if(ccode <0)
{
HandleCcode(hDlg, ccode, "NWDSInitBuf");
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return(ccode);
}
ccode = NWDSPutAttrName(gContext,inBuf,attrName);
if(ccode <0)
{
HandleCcode(hDlg, ccode, "NWDSPutAttrName");
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return(ccode);
}
do
{
ccode = NWDSRead(gContext, /* Context Handle (IN) */
currObjName, /* name of object (IN) */
DS_ATTRIBUTE_VALUES, /* a #define (IN) */
FALSE, /* #define as 1 (IN) */
inBuf, /* Attribute names (IN) */
&iterationHandle, /* iteration Handle (OUT) */
outBuf); /* Output Buffer (OUT) */
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSRead");
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return(ccode);
}
ccode = NWDSGetAttrCount(gContext, outBuf, &totalAttrs);
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSGetAttrCount");
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return(ccode);
}
if((NWCOUNT)0 == totalAttrs)
{
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return(TRUE);
}
else
{
ccode = NWDSGetAttrName(gContext, outBuf, currAttr, &valCount, &syntax);
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSGetAttrName");
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return(ccode);
}
for(j = 0; j < valCount; j++)
{
/* Note that the attribute value size is computed each time a value
is read. Each attribute may have multiple values and each value
may be a different size */
ccode = NWDSComputeAttrValSize(gContext, outBuf, syntax, &attrSize);
if(ccode < 0)
{
HandleCcode(hDlg, ccode, "NWDSComputeAttrValSize");
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return(ccode);
}
if((hattrValue = LocalAlloc(LHND, (UINT) attrSize))==NULL)
{
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return(ccode);
}
attrValue = LocalLock(hattrValue);
ccode = NWDSGetAttrVal(gContext, outBuf, syntax, attrValue);
if(ccode < 0)
break;
switch(syntax) /* for syntax reference see the */
{ /* NDS Schema Specification */
case SYN_BACK_LINK :
sprintf(tmpBuffer,"%lu\r\n%s\r\n",((Back_Link_T *)attrValue)->remoteID,((Back_Link_T *)attrValue)->objectName);
break;
case SYN_BOOLEAN :
sprintf(tmpBuffer,"%s\r\n", ((*((uint8 *)attrValue)) ? "TRUE" : "FALSE"));
break;
case SYN_CI_LIST :
sprintf(tmpBuffer,"%s\r\n", ((CI_List_T *)attrValue)->s);
break;
case SYN_COUNTER :
sprintf(tmpBuffer,"%lu\r\n", *((uint32 *)attrValue));
break;
case SYN_CE_STRING : /* All of these are strings */
case SYN_CI_STRING : /* and therefore are all */
case SYN_NU_STRING : /* printed the same way */
case SYN_PR_STRING :
case SYN_TEL_NUMBER :
case SYN_CLASS_NAME :
case SYN_DIST_NAME :
sprintf(tmpBuffer,"%s\r\n",(char *)attrValue);
break;
case SYN_EMAIL_ADDRESS :
sprintf(tmpBuffer,"%lu, %s\r\n", ((EMail_Address_T *)attrValue)->type, ((EMail_Address_T *)attrValue)->address);
break;
case SYN_FAX_NUMBER :
sprintf(tmpBuffer,"%s\r\n",((Fax_Number_T *)attrValue)->telephoneNumber);
break;
case SYN_HOLD :
sprintf(tmpBuffer,"%s, %lu\r\n",((Hold_T *)attrValue)->objectName,((Hold_T *)attrValue)->amount);
break;
case SYN_INTEGER :
case SYN_INTERVAL :
sprintf(tmpBuffer,"%lu\r\n",*((uint32 *)attrValue));
break;
case SYN_NET_ADDRESS :
sprintf(tmpBuffer,"Address Type:%lu\r\nAddress Length:%lu\r\nAddress:%02X%02X%02X%02X:%02X%02X%02X%02X%02X%02X\r\n", ((Net_Address_T *)attrValue)->addressType,((Net_Address_T *)attrValue)->addressLength,((Net_Address_T *)attrValue)->address[0],((Net_Address_T *)attrValue)->address[1],((Net_Address_T *)attrValue)->address[2],((Net_Address_T *)attrValue)->address[3],((Net_Address_T *)attrValue)->address[4],((Net_Address_T *)attrValue)->address[5],((Net_Address_T *)attrValue)->address[6],((Net_Address_T *)attrValue)->address[7],((Net_Address_T *)attrValue)->address[8],((Net_Address_T *)attrValue)->address[9]);
break;
case SYN_OBJECT_ACL :
DecodeRights(((Object_ACL_T *)attrValue)->protectedAttrName, rightsstr, ((Object_ACL_T *)attrValue)->privileges);
sprintf(tmpBuffer,"%s %s %s\r\n",((Object_ACL_T *)attrValue)->protectedAttrName,rightsstr,((Object_ACL_T *)attrValue)->subjectName);
break;
case SYN_OCTET_LIST :
sprintf(tmpBuffer,"Because the syntax SYN_OCTET_LIST is a linked list\r\nit is not shown here\r\n");
break;
case SYN_OCTET_STRING :
sprintf(tmpBuffer,"Length: 0x%x\r\nData: 0x%x\r\n",((Octet_String_T *)attrValue)->length, (uint8 *)((Octet_String_T *)attrValue)->data);
break;
case SYN_PATH :
sprintf(tmpBuffer,"Name Space Type: %lu\r\n%s:%s\r\n",((Path_T *)attrValue)->nameSpaceType,((Path_T *)attrValue)->volumeName,((Path_T *)attrValue)->path);
break;
case SYN_PO_ADDRESS :
sprintf(tmpBuffer,"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n",((char **)attrValue)[0],((char **)attrValue)[1],((char **)attrValue)[2],((char **)attrValue)[3],((char **)attrValue)[4],((char **)attrValue)[5]);
break;
case SYN_REPLICA_POINTER :
sprintf(tmpBuffer,"serverName: %s\r\nreplicaType: %lu\r\nreplicaNumber: %u\r\ncount: %lu\r\nReplica_Pointer_T.Net_Address_T not shown\r\n", ((Replica_Pointer_T *)attrValue)->serverName,((Replica_Pointer_T *)attrValue)->replicaType,((Replica_Pointer_T *)attrValue)->replicaNumber,((Replica_Pointer_T *)attrValue)->count);
break;
case SYN_STREAM :
ccode = NWDSOpenStream(gContext, currObjName, currAttr, (NWDS_FLAGS)1, &fHandle);
if(!ccode)
_lread(fHandle, (void *)tmpBuffer, DEFAULT_MESSAGE_LEN);
else
{
sprintf(tmpBuffer,"NWDSOpenStream returned: %d",ccode);
MessageBox(hDlg, tmpBuffer, "View Attributes Error", MB_OK);
}
close(fHandle);
break;
case SYN_TIME :
unixtodos(*((uint32 *)attrValue), &dt, &tm);
sprintf(tmpBuffer,"%d-%d-%d %d:%d:%d\r\n", dt.da_mon, dt.da_day, dt.da_year, tm.ti_hour, tm.ti_min, tm.ti_sec);
break;
case SYN_TIMESTAMP :
unixtodos(((NWDS_TimeStamp_T *)attrValue)->wholeSeconds, &dt, &tm);
sprintf(tmpBuffer,"%d-%d-%d %d:%d:%d\r\n%lu\r\n", dt.da_mon, dt.da_day, dt.da_year, tm.ti_hour, tm.ti_min, tm.ti_sec, ((NWDS_TimeStamp_T *)attrValue)->eventID);
break;
case SYN_TYPED_NAME :
sprintf(tmpBuffer,"0x%x, 0x%x, 0x%x\r\n", ((Typed_Name_T *)attrName)->objectName, ((Typed_Name_T *)attrName)->level, ((Typed_Name_T *)attrName)->interval);
break;
default :
sprintf(tmpBuffer,"Unrecognized Sytax\r\n");
break;
}
if(!((strlen(txtBuffer)) + (strlen(txtBuffer)) > DEFAULT_MESSAGE_LEN))
strcat(txtBuffer,tmpBuffer);
else
{
MessageBox(hDlg, "The Attribute you are reading holds more information\nthan is displayed but cannot be shown here.", "Memory Limit Reached", MB_OK);
j= (int) valCount;
iterationHandle = -1L;
}
SetDlgItemText(hDlg, IDC_ATTR_VALUES, txtBuffer);
LocalUnlock(hattrValue);
LocalFree(hattrValue);
}
}
}
while(iterationHandle != -1L);
GlobalUnlock(htxtBuffer);
GlobalFree(htxtBuffer);
GlobalUnlock(htmpBuffer);
GlobalFree(htmpBuffer);
NWDSFreeBuf(inBuf);
NWDSFreeBuf(outBuf);
return 0;
}
/***************************************************************************
** This procedure takes a list of rights (normally from an ACL) and
** translates then from the variable "privs" to a text format that is
** common to most network utilities.
*/
void DecodeRights(char *attrName, char *rightsstring, NWDS_PRIVILEGES privs)
{
strset(rightsstring, '\x0');
strcat(rightsstring, "[");
if(!strcmp(attrName, "[Entry Rights]"))
{
if(privs & 0x01) /* DS_ENTRY_BROWSE */
strcat(rightsstring, "B");
else
strcat(rightsstring, " ");
if(privs & 0x02) /* DS_ENTRY_ADD */
strcat(rightsstring, "A");
else
strcat(rightsstring, " ");
if(privs & 0x04) /* DS_ENTRY_DELETE */
strcat(rightsstring, "D");
else
strcat(rightsstring, " ");
if(privs & 0x08) /* DS_ENTRY_RENAME */
strcat(rightsstring, "R");
else
strcat(rightsstring, " ");
if(privs & 0x10) /* DS_ENTRY_SUPERVISOR */
strcat(rightsstring, "S");
else
strcat(rightsstring, " ");
}
else
{
if(!strcmp(attrName, "[SMS Rights]"))
{
if(privs & 0x01) /* DS_SMS_SCAN */
strcat(rightsstring, "S");
else
strcat(rightsstring, " ");
if(privs & 0x02) /* DS_SMS_BACKUP */
strcat(rightsstring, "B");
else
strcat(rightsstring, " ");
if(privs & 0x04) /* DS_SMS_RESTORE */
strcat(rightsstring, "R");
else
strcat(rightsstring, " ");
if(privs & 0x08) /* DS_SMS_RENAME */
strcat(rightsstring, "C");
else
strcat(rightsstring, " ");
if(privs & 0x10) /* DS_SMS_DELETE */
strcat(rightsstring, "D");
else
strcat(rightsstring, " ");
if(privs & 0x20) /* DS_SMS_ADMIN */
strcat(rightsstring, "A");
else
strcat(rightsstring, " ");
}
else /* Attribute Rights which applies to all others */
{
if(privs & 0x01) /* DS_ATTR_COMPARE */
strcat(rightsstring, "C");
else
strcat(rightsstring, " ");
if(privs & 0x02) /* DS_ATTR_READ */
strcat(rightsstring, "R");
else
strcat(rightsstring, " ");
if(privs & 0x04) /* DS_ATTR_WRITE */
strcat(rightsstring, "W");
else
strcat(rightsstring, " ");
if(privs & 0x08) /* DS_ATTR_SELF */
strcat(rightsstring, "A");
else
strcat(rightsstring, " ");
if(privs & 0x20) /* DS_ATTR_SUPERVISOR */
strcat(rightsstring, "S");
else
strcat(rightsstring, " ");
}
}
strcat(rightsstring,"]\x0");
}