/****************************************************************************

  $Archive: $
  $Revision: $
  $Modtime: $
 
 Copyright (c) 1998 Novell, Inc. All Rights Reserved.

 THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
 USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
 ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
 PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
 ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
 PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
 DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
 PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
 CUSTOMERS WITH RESPECT TO THIS CODE.

 ****************************************************************************/

/*************************************************************************
  BINSCAN.C
**************************************************************************

  BINSCAN demonstrates how to scan and return Bindery information based
  on user input.  BINSCAN accepts the following three parameters:
     
     Server      - Read the Bindery from this server
     Object Name - Name of the object to scan, can be wild (*)
     Object Type - Decimal type of object to be scanned, optional
                   Object types are as follows:

                      0.  Unknown
                      1.  User
                      2.  User Group
                      3.  Print Queue
                      4.  File Server
                      5.  Job Server
                      6.  Gateway
                      7.  Print Server
                      8.  Archive Queue
                      9.  Archive Server
                      10. Job Queue
                      11. Administration

  Usage:  BINSCAN <server name> <object name> [object type]
   
           List all users in MYSERVER Bindery :  BINSCAN MYSERVER * 1  
           List all objects called ADMIN      :  BINSCAN MYSERVER ADMIN
           List all objects                   :  BINSCAN MYSERVER *
           List file server RED               :  BINSCAN MYSERVER RED 4

*************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <ntypes.h>
#include <nwclxcon.h>
#include <nwbindry.h>
#include <nwmisc.h>

#ifdef N_PLAT_NLM         /* ThreadSwitchWithDelay(), applicable */
   #include <nwthread.h>  /* only to NLM platform                */
#endif

static nint8 *security_msg[] = {
      "Anyone", "Logged", "Object", "Supervisor", "NWOS"};

static nint8 *otype_msg[] = {
      "Unknown","User","User Group","Print Queue","File Server","Job Server",
      "Gateway","Print Server","Archive Queue","Archive Server","Job Queue",
      "Administration"};

/*---------------------------------------------------------------------*/

main(int argc, char *argv[])
{
   
   NWCONN_HANDLE   connHandle;
   NWCCODE         rc, ccode;
   nint32          id2;
   nint16          I, J, tindex;
   nint8           buff[48];
   nuint16         tmpType;

   /* Variables for NWScanObject */

   nstr8           searchObjectName[48];
   nstr8           serverName[NW_MAX_SERVER_NAME_LEN];
   nuint16         searchObjectType;
   nuint32         objectID = 0xFFFFFFFF;  /* -1 */
   nstr8           objectName[48];
   nuint16         objectType;
   nuint8          objectHasProperties;
   nuint8          objectFlag;
   nuint8          objectSecurity;
   
   /* Variables for NWScanProperty */
   
   nstr8           searchPropertyName[15];
   nuint32         sequenceNumber = 0xFFFFFFFF;  /* -1 */
   nstr8           propertyName[15];
   nuint8          propertyFlags;
   nuint8          propertySecurity;
   nuint8          propertyHasValue;
   nuint8          moreProperties;
   
   /* Variables for NWReadPropertyValue */
   
   nuint8         dataSetIndex;
   nuint8         propertyValue[128];
   nuint8         moreSegments;


   printf("\nBinScan: ");

   if (argc > 2)
   {
      strcpy(serverName, strupr(argv[1]));
      strcpy(searchObjectName,strupr(argv[2]));
      searchObjectType = OT_WILD;

      if (argc > 3)
         searchObjectType = (NWWordSwap)((nuint16)atoi(argv[3]));
   }
   else
   {
      printf("\n     usage: BINSCAN <server> <object name> [object type]\n");
      printf("\n            server      - scan Bindery of this server.");
      printf("\n            object name - * wild, else object name.");
      printf("\n            object type - decimal # for object type.\n");
      exit(1);
   }

   /* Initialize Libraries */

   rc = NWCallsInit(NULL, NULL);
   if(rc)
   {
      printf("\nNWCallsInit: failed %04x",rc);
      exit(1);
   }

   /* Establish a connection to a server before reading the Bindery */

   ccode = NWCCOpenConnByName(
           /*  start Conn Handle */ 0,  
           /*  name              */ serverName,
           /*  name format       */ NWCC_NAME_FORMAT_BIND,
           /*  open state        */ NWCC_OPEN_UNLICENSED,
           /*  tran type         */ NWCC_TRAN_TYPE_WILD,
           /*  Connection Handle */ &connHandle);

   if(ccode)
   {
      printf( "\nNWCCOpenConnByName: failed %04x", ccode );
      exit(1);
   }

   printf("\nScanning for '%s' ", searchObjectName);

   while(! NWScanObject(connHandle,        
                        searchObjectName,    
                        searchObjectType,    
                        &objectID,           
                        objectName,          
                        &objectType,         
                        &objectHasProperties,
                        &objectFlag,         
                        &objectSecurity))
   {
      tindex = -1;

      switch (NWWordSwap(objectType))
      {
         case 0x0000:
         {
            tindex = 0; 
            break;
         }
         case 0x0001: 
         {
            tindex = 1; 
            break;
         }
         case 0x0002:
         {
            tindex = 2; 
            break;
         }
         case 0x0003: 
         {
            tindex = 3; 
            break;
         }
         case 0x0004: 
         {
            tindex = 4; 
            break;
         }
         case 0x0005: 
         {
            tindex = 5; 
            break;
         }
         case 0x0006: 
         {
            tindex = 6; 
            break;
         }
         case 0x0007: 
         {
            tindex = 7; 
            break;
         }
         case 0x0008: 
         {
            tindex = 8; 
            break;
         }
         case 0x0009: 
         {
            tindex = 9; 
            break;
         }
         case 0x000A: 
         {
            tindex = 10; 
            break;
         }
         case 0x000B: 
         {
            tindex = 11; 
            break;
         }
         case 0x0021: 
         {
            strcpy(buff,"NAS SNA Gateway"); 
            break;
         }
         case 0x0026: 
         {
            strcpy(buff,"Remote Bridge Server"); 
            break;
         }
         case 0x0027: 
         {
            strcpy(buff,"TCPIP Gateway"); 
            break;
         }
         case 0x0278: 
         {
            strcpy(buff,"Tree Name"); 
            break;
         }
         case 0xffff: 
         {
            strcpy(buff,"Unknown"); 
            break;
         }
         default:     
         {
            strcpy(buff,"Unrecognized"); 
            break;
         }
      } /* switch */

      printf("\nObject: %s [%lx] <%s> - type %04x",
             objectName, objectID,
             (tindex == -1 ? buff : otype_msg[tindex]),
             NWWordSwap(objectType));

      /* low nibble of objectSecurity controls Read security and the high 
         nibble controls Write security. Read security determines which 
         clients can find the bindery object when they scan for it. Write 
         security defines which clients can create properties 
         for the bindery object */

      printf("\n\tSecurity: <Scan by '%s': Add by '%s'>",
             security_msg[objectSecurity & 0x0f],
             security_msg[(objectSecurity & 0xf0) >> 4]);

      if (objectHasProperties)
      {
         /*  Get the access security for Scanning and Added
             to the Bindery */

         printf("\n\nProperties:");
         sequenceNumber = 0xFFFFFFFF; /* -1 */
         strcpy(searchPropertyName,"*");

         while (! NWScanProperty(connHandle,
                                 objectName,
                                 objectType,
                                 searchPropertyName,
                                 &sequenceNumber,
                                 propertyName,
                                 &propertyFlags,
                                 &propertySecurity,
                                 &propertyHasValue,
                                 &moreProperties))
         {
            printf("\n\t%s",propertyName);

            printf("\n\tSecurity: <Scan by '%s': Add by '%s'>",
                   security_msg[propertySecurity & 0x0f],
                   security_msg[(propertySecurity & 0xf0) >> 4]);

            if (propertyHasValue)
            {
               dataSetIndex = 1;
               do
               {
                  rc = NWReadPropertyValue(connHandle,
                                           objectName,
                                           objectType,
                                           propertyName,
                                           dataSetIndex,
                                           propertyValue,
                                           &moreSegments,
                                           &propertyFlags); 
                  if(! rc)
                  {
                     if (dataSetIndex == 1)
                     {
                        printf("\n\t\tValues <%s-%s>:",
                               ((propertyFlags & 1) ? "dynamic":"static"),
                               ((propertyFlags & 2) ? "Set"    :"Item"  ));
                     }

                     printf("\n\t\t");

                     if ((strcmp(propertyName,"IDENTIFICATION") == 0) ||
                         (strcmp(propertyName,"HOMEDIRPATH") == 0) )
                        printf(" %02x",propertyValue);
                     else if (propertyFlags & 2)  /* property type BF_SET */
                     {
                        for (J = 0, I = 0; I < 32; I++)
                        {
                           id2 = *(long *)&propertyValue[I * 4];
                           if (id2)
                           {
                              rc = NWGetObjectName(connHandle,
                                                   id2,
                                                   buff,
                                                   &tmpType);
                              if(rc)
                              {
                                 printf(buff,
                                        "NWGetObjectName: failed %04x\n",rc);
                                 strcat(buff, NULL);
                              }

                              printf("%-20.20s ",buff);
                              if(++J > 2) 
                              {
                                 J = 0;
                                 printf("\n\t\t");
                              } /* if */
                           } /* if */
                        } /* for */
                     }
                     else   
                     {
                        for (J = 0, I = 0; I < 128; I++)
                        {
                           printf(" %02x",propertyValue[I]);
                           if (++J > 15)
                           {
                              J = 0;
                              printf("\n\t\t");
                           }
                        } /* for */
                     }
                     dataSetIndex++;    /* advance for next set */
                  } /* if */

                  #ifdef N_PLAT_NLM       /* Thread switch for NLMs */
                     ThreadSwitchWithDelay();  
                  #endif
               } while(moreSegments && !rc);
            } /* if */
         } /* while */
      } /* if */
      printf("\n--------------------------------------------------");

   } /* while */

   /* close connection to server */
   ccode = NWCCCloseConn(connHandle);
   if(ccode)
      printf("\nNWCCCloseConn: failed %04lX", ccode);

   return(rc);

} /* main */


