home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / xdsa1.exe / DSACCESS.C next >
Text File  |  1994-10-21  |  31KB  |  916 lines

  1. /*****************************************************************************
  2. ** File: dsaccess.c
  3. **
  4. **    Description:
  5. **        Contains source for DSSearchOpen, DSSearchSeek, DSRead, and DSClose.
  6. **        These functions provide a streams type interface to NDS x.500
  7. **        compliant calls, simplifying searches for information in the directory.
  8. **
  9. **    Disclaimer:
  10. **
  11. **        Novell, Inc. makes no representations or warranties with respect to
  12. **        any NetWare software, and specifically disclaims any express or
  13. **        implied warranties of merchantability, title, or fitness for a
  14. **        particular purpose.  
  15. **
  16. **        Distribution of any NetWare software is forbidden without the
  17. **        express written consent of Novell, Inc.  Further, Novell reserves
  18. **        the right to discontinue distribution of any NetWare software.
  19. **
  20. **        Novell is not responsible for lost profits or revenue, loss of use
  21. **        of the software, loss of data, costs of re-creating lost data, the
  22. **        cost of any substitute equipment or program, or claims by any party
  23. **        other than you.  Novell strongly recommends a backup be made before
  24. **        any software is installed.   Technical support for this software
  25. **        may be provided at the discretion of Novell.
  26. **
  27. ** Programmers:
  28. **
  29. **    Ini   Who                  Firm
  30. **    ------------------------------------------------------------------------
  31. **    MDO   Mark D. Oberg            Novell Developer Support
  32. **
  33. **
  34. ** History:
  35. **
  36. **    When            Who   What
  37. **    ------------------------------------------------------------------------
  38. **     09-22-94     MDO    Begin
  39. **        10-03-94        MDO    Tested
  40. **
  41. */
  42.  
  43. /*****************************************************************************
  44. ** Include files and macro definitions
  45. */
  46.    /*-------------------------------------------------------------------------
  47.    ** ANSI Includes
  48.    */
  49.     #include <stdio.h>
  50.     #include <stdlib.h>
  51.     #include    <string.h>
  52.  
  53.    /*-------------------------------------------------------------------------
  54.    ** NetWare Includes
  55.    */
  56.     #include <nwdsapi.h>
  57.     #include <nwdsmisc.h>
  58.     #include <nwdsdc.h>
  59.     #include <nwconn.h>
  60.     #include <nwenvrn.h>
  61.     #include <nwcntask.h>
  62.  
  63.    /*-------------------------------------------------------------------------
  64.    ** SRCHMAN
  65.    */
  66.    #include "dsaccess.h"
  67.  
  68. /*****************************************************************************
  69. ** Function Prototypes used only in this module.
  70. */
  71. NWDSCCODE DSAllocAndInitAttrNamesBuffer(DS_HANDLE *dsHandle, char **attrNames);
  72. NWDSCCODE _DSSearch(DS_HANDLE *dsHandle);
  73. NWDSCCODE _DSRead(DS_HANDLE *dsHandle);
  74.  
  75.  
  76. /*****************************************************************************
  77. **    Syntax:    #include <dsaccess.h>
  78. **
  79. **                DS_HANDLE    *DSSearchOpen(
  80. **                    NWDSContextHandle    context,
  81. **                    char *attrNames[],
  82. **                    TOKEN_ENTRY    tokens[]);
  83. **
  84. **    Parameters:
  85. **                context
  86. **                    input-Provides a directory services context for calls to use.
  87. **
  88. **                attrNames[]
  89. **                    input-Tells DSSearch what attributes to return during the
  90. **                            search.  Initialize the last entry with NULL value to
  91. **                            terminate the array.  If NULL is passed in, all attributes
  92. **                            will be returned on subsequest DSSearch and DSRead calls.
  93. **
  94. **                tokens[]
  95. **                    input-Describes the expression tree to be used to select
  96. **                            what objects information will be returned.  Each entry
  97. **                            will be used as parameters to a call to NWDSAddFilterToken.
  98. **                            The last entry should be a FTOK_END, this terminates the
  99. **                            array as well as the expression tree.  
  100. **
  101. **    Return Value:
  102. **                A pointer to a DS_HANDLE which includes all buffers and
  103. **                interation handles setup to execute a DSSearch call.
  104. **                NULL if unsuccessful.
  105. **
  106. **    Remarks:    DSClose is called after the handle is no longer needed.
  107. **
  108. */
  109. DS_HANDLE *DSSearchOpen(NWDSContextHandle cx,
  110.                                 char **attrNames,
  111.                                 TOKEN_ENTRY *tokent)
  112.     {
  113.     NWDSCCODE    ccode;
  114.     NWCOUNT    tokenCount;        /* 1-4G */
  115.     DS_HANDLE *dsHandle;
  116.     NWDS_FILTER_CURSOR *cur;
  117.  
  118.     /*-------------------------------------------------------------------------
  119.     ** calculate size and allocate the buffers first.
  120.     */
  121.     if(NULL==(dsHandle=malloc(sizeof(DS_HANDLE))))
  122.         goto Exit0;
  123.  
  124.     /*-------------------------------------------------------------------------
  125.     ** Save context in handle because the same context needs to be used
  126.     **    in setting up filters and doing the NWDSSearch.
  127.     */
  128.     dsHandle->context=cx;
  129.     dsHandle->countObjectsToSearch=0;    /* not currently used. */
  130.     dsHandle->handleType=DSV_SEARCH;              /* doing NWDSSearch*/
  131.     dsHandle->objectInfoSize=DEFAULT_MESSAGE_LEN;    /* 4K */
  132.  
  133.     /*-------------------------------------------------------------------------
  134.     ** attrNames specify what attribute names values are wanted to be returned
  135.     **    during a search.  If none are specified DSSearch will return names
  136.     ** for all values.
  137.     */
  138.     ccode=DSAllocAndInitAttrNamesBuffer(dsHandle, attrNames);
  139.     if(ccode)
  140.         goto Exit1;
  141.  
  142.     /*-------------------------------------------------------------------------
  143.     ** objectInfo holds the object names, attribute names and attribute
  144.     **    values returned by a NWDSSearch or NWDSRead.  objectInfo starts
  145.     ** out at a default size of 4K.  If a value can't fit into the 4K buffer
  146.     ** during a search or read, the buffer should be re-allocated until it
  147.     **    fits.  Values have a maximum size of 64K, (Streams is an exception to
  148.     **    this and is only limited by disk space.)  If NWDSSearch or NWDSRead
  149.     ** returns ERR_INSUFFICIENT_BUFFER, the buffer should be reallocated and
  150.     **    the search or read attempted again until the buffer reaches a size of
  151.     **    64K. At that point something else must be wrong.
  152.     */
  153.     ccode=NWDSAllocBuf(
  154.         /* size_t    size,                        */ dsHandle->objectInfoSize,     
  155.         /* Buf_T        NWFAR * NWFAR *buf    */ &dsHandle->objectInfo    );
  156.  
  157.     if(ccode)
  158.         goto Exit2;
  159.  
  160.     /*-------------------------------------------------------------------------
  161.     ** Allocate and initialize the filter for search.
  162.     */
  163.     ccode=NWDSAllocBuf(
  164.         /* size_t    size,                        */    DEFAULT_MESSAGE_LEN , /* 4K, modify later to be optimized. */
  165.         /* Buf_T        NWFAR * NWFAR *buf    */ &dsHandle->filter    );
  166.  
  167.     if(ccode)
  168.         goto Exit3;
  169.     
  170.     ccode=NWDSInitBuf(
  171.     /*    NWDSContextHandle        context, */    cx,
  172.     /*    uint32    operation,                 */    DSV_SEARCH_FILTER,
  173.     /*    Buf_T        NWFAR *buf                */    dsHandle->filter );
  174.     if(ccode)
  175.         goto Exit4;
  176.  
  177.     if(tokent)
  178.         {
  179.         ccode=NWDSAllocFilter(&cur);
  180.         if(ccode)
  181.             goto Exit4;
  182.  
  183.         /*----------------------------------------------------------------------
  184.         ** put in the filter tokens.
  185.         */
  186.         tokenCount=0;
  187.         do
  188.             {
  189.             ccode = NWDSAddFilterToken(cur, tokent[tokenCount].tok,
  190.                     tokent[tokenCount].val, tokent[tokenCount].syn);
  191.             if(ccode)
  192.                 goto Exit5;
  193.             }while(FTOK_END!=tokent[tokenCount++].tok);
  194.  
  195.         }
  196.     else
  197.         goto Exit4;
  198.  
  199.     /*-------------------------------------------------------------------------
  200.     ** Transfer the filter tree to the filter buffer.  This frees filter
  201.     **    cursor.
  202.     */
  203.     ccode=NWDSPutFilter(cx, dsHandle->filter, cur, NULL);
  204.     if(ccode)
  205.         goto Exit4;        /* do not Free Filter if failure on NWDSPutFilter */
  206.  
  207.     return(dsHandle);        /* Success! */
  208.  
  209. Exit5:
  210.     NWDSFreeFilter(cur,NULL);
  211. Exit4:    
  212.     NWDSFreeBuf(dsHandle->filter);    
  213. Exit3:
  214.     NWDSFreeBuf(dsHandle->objectInfo);
  215. Exit2:
  216.     if(dsHandle->attrNames)
  217.         NWDSFreeBuf(dsHandle->attrNames);
  218. Exit1:
  219.     free(dsHandle);
  220. Exit0:
  221.     return(NULL);        /* Failure.... */
  222.     }    
  223.                             
  224. /*****************************************************************************
  225. **    Syntax:    #include <dsaccess.h>
  226. **
  227. **                NWDSCCODE    DSSearchSeek(
  228. **                                        DS_HANDLE *dsHandle,
  229. **                                        char *baseObjectName,
  230. **                                        NWDS_SEARCH_SCOPE scope,
  231. **                                        NWFLAGS    searchAliases,
  232. **                                        NWDS_TYPE    infoType );
  233. ** Parameters:
  234. **                dsHandle
  235. **                    input-takes the search handle returned by a call to
  236. **                            DSSeekOpen.
  237. **
  238. **                baseObjectName
  239. **                    input-specifies where to start the search from.  Can be a
  240. **                            container or a specific object.
  241. **
  242. **                scope
  243. **                    input-specifies how to search from the base object.  Options
  244. **                            are DS_SEARCH_ENTRY (searches the baseObjectName only),
  245. **                            DS_SEARCH_SUBORDINATES (searches the baseObjectName and
  246. **                            immediate subordinates if baseObjectName is a container), or
  247. **                            DS_SEARCH_SUBTREEE (searches baseObjectNameand all objects
  248. **                            below the baseObjectName.)
  249. **
  250. **                searchAliases
  251. **                    input-accepts a value of TRUE or FALSE.  TRUE tells NWDSSearch
  252. **                            to continue searches in the container of aliased objects.
  253. **                            FALSE is the recommeded setting to avoid possible
  254. **                            circular searches.
  255. **
  256. **                infoType
  257. **                    input-accepts a value of 0 or 1.  0 specifies to return
  258. **                            attribute names only.  1 specifies to return attribute
  259. **                            names and values.  Attribute names and values allowed
  260. **                            to be returned are described in the DSSearchOpen call by
  261. **                            the attrNames field.
  262. **
  263. **    Return Value:
  264. **                DSSearchSeek returns zero if no error, otherwise returns
  265. **                ccode from the NWDSSearch call, consult netware error
  266. **                codes for interpretation.
  267. **
  268. **    Remarks:    DSSearchSeek causes NDS to be queried and receives object names, object
  269. **                information, attribute names and attribute values in a buffer
  270. **                that may be read by DSRead.  Information contained in the buffer
  271. **                after a DSSeek call meets the search criteria specified in the
  272. **                DSSearchOpen's tokens field.  Only attribute names and values
  273. **                specified in the DSSearchOpen's attrNames field are returned.  A
  274. **                NULL value passed into the DSSearchOpen's attrNames field specifies
  275. **                to return all attribute names and values for all attributes of a
  276. **                found    object.
  277. **                
  278. **
  279. */
  280. NWDSCCODE    DSSearchSeek(
  281.                         DS_HANDLE *dsHandle,
  282.                         char *baseObjectName,
  283.                         NWDS_SEARCH_SCOPE scope,
  284.                         NWFLAGS    searchAliases,
  285.                         NWDS_TYPE    infoType    )
  286.     {
  287.     /*-------------------------------------------------------------------------
  288.     ** save this information for future interations of search.
  289.     */
  290.     strcpy(dsHandle->baseObjectName,baseObjectName);
  291.     dsHandle->scope=scope;
  292.     dsHandle->searchAliases=searchAliases;
  293.     dsHandle->infoType=infoType;
  294.     dsHandle->iteration=NO_MORE_ITERATIONS;    /* setup for first NWDSSearch */
  295.     dsHandle->readState=NEW_SEARCH;
  296.     
  297.     return(_DSSearch(dsHandle));
  298.     }
  299.  
  300. /*****************************************************************************
  301. ** used in DSSearchSeek and DSRead.
  302. */
  303. NWDSCCODE    _DSSearch(DS_HANDLE *dsHandle)
  304.     {
  305.     NWDSCCODE ccode;
  306.     
  307.     do
  308.         {
  309.         ccode=NWDSSearch(
  310.             /* NWDSContextHandle        context,                */    dsHandle->context,
  311.             /* char        NWFAR *baseObjectName,            */    dsHandle->baseObjectName,
  312.             /* int        scope,                                */    dsHandle->scope,
  313.             /* uint8        searchAliases,                        */    dsHandle->searchAliases,
  314.             /* Buf_T        NWFAR *filter,                        */    dsHandle->filter,
  315.             /* uint32    infoType,                            */    dsHandle->infoType,
  316.             /* uint8        allAttrs,                              */    dsHandle->attrNames ? FALSE : TRUE,
  317.             /* Buf_T        NWFAR *attrNames,                    */    dsHandle->attrNames,
  318.             /* int32        NWFAR *iterationHandle,            */    &dsHandle->iteration,
  319.             /* int32        countObjectsToSearch,            */    dsHandle->countObjectsToSearch,
  320.             /* int32        NWFAR *countObjectsSearched,    */    &dsHandle->countObjectsSearched,
  321.             /* Buf_T        NWFAR *objectInfo                    */    dsHandle->objectInfo );
  322.  
  323.         if(ERR_INSUFFICIENT_BUFFER==ccode)
  324.             {
  325.             dsHandle->objectInfoSize<<=1;            /* double buffer size */
  326.  
  327.             /*-------------------------------------------------------------------
  328.             ** max attribute value size is 64k-room for object and attribute
  329.             **    name. something else must be wrong.
  330.             */
  331.             if(0x10000<dsHandle->objectInfoSize)
  332.                 return(ERR_SYSTEM_FAILURE);
  333.             
  334.             free(dsHandle->objectInfo);    /* return and will alloc again */
  335.  
  336.             ccode=NWDSAllocBuf(
  337.                 /* size_t    size,                        */ dsHandle->objectInfoSize,   
  338.                 /* Buf_T        NWFAR * NWFAR *buf    */ &dsHandle->objectInfo    );
  339.  
  340.             if(ccode)    
  341.                 dsHandle->objectInfo=NULL;        /* if not alloced, let DSClose know it */
  342.             else
  343.                 ccode=ERR_INSUFFICIENT_BUFFER; /* success, try DSSearch again */
  344.             }
  345.         }while (ERR_INSUFFICIENT_BUFFER==ccode);
  346.  
  347.     return(ccode);            /* normal exit may be an error */
  348.     }
  349.  
  350. /*****************************************************************************
  351. **    Syntax:    #include <dsaccess.h>
  352. **
  353. **                DS_HANDLE    *DSReadOpen(
  354. **                    NWDSContextHandle    context,
  355. **                    char *attrNames[] );
  356. **
  357. **    Parameters:
  358. **                context
  359. **                    input-Provides a directory services context for calls to use.
  360. **
  361. **                attrNames[]
  362. **                    input-Tells DSSearch what attributes to return during the
  363. **                            search.  Initialize the last entry with NULL value to
  364. **                            terminate the array.
  365. **
  366. **    Return Value:
  367. **                A pointer to a DS_HANDLE which includes all buffers and
  368. **                interation handles setup to execute a NWDSRead.
  369. **                NULL if unsuccessful.
  370. **
  371. **    Remarks:    DSClose is called after the handle is no longer needed.
  372. **
  373. */
  374. DS_HANDLE *DSReadOpen(NWDSContextHandle cx,
  375.                                 char **attrNames)
  376.     {
  377.     NWDSCCODE    ccode;
  378.     DS_HANDLE *rHand;
  379.  
  380.     /*-------------------------------------------------------------------------
  381.     ** Allocate DS_HANDLE
  382.     */
  383.     if(NULL==(rHand=malloc(sizeof(DS_HANDLE))))
  384.         goto Exit0;
  385.  
  386.     /*-------------------------------------------------------------------------
  387.     ** Save context in handle because the same context needs to be used
  388.     **    in setting up filters and doing the NWDSSearch.
  389.     */
  390.     rHand->context=cx;
  391.     rHand->objectInfoSize=DEFAULT_MESSAGE_LEN;    /* 4K Initial size */
  392.     rHand->handleType=DSV_READ;        /* doing an NWDSRead */
  393.     
  394.     /*-------------------------------------------------------------------------
  395.     ** Allocate and initialize the attr names buffer.
  396.     */
  397.     ccode=DSAllocAndInitAttrNamesBuffer( rHand, attrNames);
  398.     if(ccode)
  399.         goto Exit1;
  400.     /*-------------------------------------------------------------------------
  401.     ** objectInfo holds the object names, attribute names and attribute
  402.     **    values returned by a NWDSSearch or NWDSRead.  objectInfo starts
  403.     ** out at a default size of 4K.  If a value can't fit into the 4K buffer
  404.     ** during a search or read, the buffer should be re-allocated until it
  405.     **    fits.  Values have a maximum size of 64K, (Streams is an exception to
  406.     **    this and is only limited by disk space.)  If NWDSSearch or NWDSRead
  407.     ** returns ERR_INSUFFICIENT_BUFFER, the buffer should be reallocated and
  408.     **    the search or read attempted again until the buffer reaches a size of
  409.     **    64K. At that point something else must be wrong.
  410.     */
  411.     ccode=NWDSAllocBuf(
  412.         /* size_t    size,                        */ rHand->objectInfoSize,     
  413.         /* Buf_T        NWFAR * NWFAR *buf    */ &rHand->objectInfo    );
  414.     if(ccode)
  415.         goto Exit2;
  416.     return(rHand);
  417.  
  418. Exit2:
  419.     NWDSFreeBuf(rHand->attrNames);
  420. Exit1:
  421.     free(rHand);
  422. Exit0:
  423.     return(NULL);
  424.     }
  425.  
  426. /*****************************************************************************
  427. **    Syntax:    #include <dsaccess.h>
  428. **
  429. **                NWDSCCODE    DSReadSeek(
  430. **                                        DS_HANDLE *dsHandle,
  431. **                                        char *objectName,
  432. **                                        NWDS_TYPE    infoType );
  433. ** Parameters:
  434. **                dsHandle
  435. **                    input-takes the search handle returned by a call to
  436. **                            DSSeekOpen.
  437. **
  438. **                objectName
  439. **                    input-specifies which object to read.
  440. **
  441. **                infoType
  442. **                    input-accepts a value of 0 or 1.  0 specifies to return
  443. **                            attribute names only.  1 specifies to return attribute
  444. **                            names and values.  Attribute names and values allowed
  445. **                            to be returned are described in the DSSearchOpen call by
  446. **                            the attrNames field.
  447. **
  448. **    Return Value:
  449. **                DSReadSeek returns zero if no error, otherwise returns
  450. **                ccode from the NWDSRead call, consult netware error
  451. **                codes for interpretation.
  452. **
  453. **    Remarks:    DSReadSeek causes NDS to be queried and receives object name, object
  454. **                information, attribute names and attribute values in a buffer
  455. **                that may be read by DSRead.  Only attribute names and values
  456. **                specified in the DSReadOpen's attrNames field are returned.  A
  457. **                NULL value passed into the DSReadOpen's attrNames field specifies
  458. **                to return all attribute names and values for all attributes of a
  459. **                found    object.
  460. **                
  461. **
  462. */
  463. NWDSCCODE    DSReadSeek(
  464.                         DS_HANDLE *dsHandle,
  465.                         char *objectName,
  466.                         NWDS_TYPE    infoType    )
  467.     {
  468.     /*-------------------------------------------------------------------------
  469.     ** save this information for future interations of NWDSRead.
  470.     */
  471.     strcpy(dsHandle->baseObjectName,objectName);
  472.     dsHandle->infoType=infoType;
  473.     dsHandle->iteration=NO_MORE_ITERATIONS;    /* setup for first NWDSSearch */
  474.     dsHandle->readState=NEW_READ;
  475.     
  476.     return(_DSRead(dsHandle));
  477.     }
  478.  
  479. /*****************************************************************************
  480. ** used in DSReadSeek and DSRead
  481. */
  482. NWDSCCODE    _DSRead(DS_HANDLE *dsHandle)
  483.     {
  484.     NWDSCCODE ccode;
  485.     
  486.     do
  487.         {
  488.         ccode=NWDSRead(
  489.             /* NWDSContextHandle        context,                */    dsHandle->context,
  490.             /* char        NWFAR *objectName,                */    dsHandle->baseObjectName,
  491.             /* uint32    infoType,                            */    dsHandle->infoType,
  492.             /* uint8        allAttrs,                              */    dsHandle->attrNames ? FALSE : TRUE,
  493.             /* Buf_T        NWFAR *attrNames,                    */    dsHandle->attrNames,
  494.             /* int32        NWFAR *iterationHandle,            */    &dsHandle->iteration,
  495.             /* Buf_T        NWFAR *objectInfo                    */    dsHandle->objectInfo );
  496.  
  497.         if(ERR_INSUFFICIENT_BUFFER==ccode)
  498.             {
  499.             dsHandle->objectInfoSize<<=1;            /* double buffer size */
  500.  
  501.             /*-------------------------------------------------------------------
  502.             ** max attribute value size is 64k-room for object and attribute
  503.             **    name. something else must be wrong.
  504.             */
  505.             if(0x10000<dsHandle->objectInfoSize)
  506.                 return(ERR_SYSTEM_FAILURE);
  507.             
  508.             free(dsHandle->objectInfo);    /* return and will alloc again */
  509.  
  510.             ccode=NWDSAllocBuf(
  511.                 /* size_t    size,                        */ dsHandle->objectInfoSize,   
  512.                 /* Buf_T        NWFAR * NWFAR *buf    */ &dsHandle->objectInfo    );
  513.  
  514.             if(ccode)
  515.                 dsHandle->objectInfo=NULL;            /* tell DSClose not alloc'ed. */
  516.             else
  517.                 ccode=ERR_INSUFFICIENT_BUFFER;    /* success, try search again */
  518.  
  519.             }
  520.         }while (ERR_INSUFFICIENT_BUFFER==ccode);
  521.  
  522.     return(ccode);            /* normal exit may be an error */
  523.     }
  524.  
  525. /*****************************************************************************
  526. **    Syntax:    #include <dsaccess.h>
  527. **
  528. **                DS_HANDLE    *DSListOpen(
  529. **                    NWDSContextHandle    context );
  530. **
  531. **    Parameters:
  532. **                context
  533. **                    input-Provides a directory services context for calls to use.
  534. **
  535. **                attrNames[]
  536. **                    input-Tells DSSearch what attributes to return during the
  537. **                            search.  Initialize the last entry with NULL value to
  538. **                            terminate the array.
  539. **
  540. **    Return Value:
  541. **                A pointer to a DS_HANDLE which includes all buffers and
  542. **                interation handles setup to execute a NWDSRead.
  543. **                NULL if unsuccessful.
  544. **
  545. **    Remarks:    DSClose is called after the handle is no longer needed.
  546. **
  547. */
  548. DS_HANDLE *DSListOpen(NWDSContextHandle cx)
  549.     {
  550.     NWDSCCODE    ccode;
  551.     DS_HANDLE     *dsHandle;
  552.  
  553.     /*-------------------------------------------------------------------------
  554.     ** Allocate DS_HANDLE
  555.     */
  556.     if(NULL==(dsHandle=malloc(sizeof(DS_HANDLE))))
  557.         goto Exit0;
  558.  
  559.     /*-------------------------------------------------------------------------
  560.     ** Save context in handle because the same context needs to be used
  561.     **    in setting up filters and doing the NWDSSearch.
  562.     */
  563.     dsHandle->context=cx;
  564.     dsHandle->objectInfoSize=DEFAULT_MESSAGE_LEN;    /* 4K Initial size */
  565.     dsHandle->handleType=DSV_LIST;        /* doing an NWDSList */
  566.     
  567.     /*-------------------------------------------------------------------------
  568.     ** objectInfo holds the object names, attribute names and attribute
  569.     **    values returned by a NWDSSearch or NWDSRead.  objectInfo starts
  570.     ** out at a default size of 4K.  If a value can't fit into the 4K buffer
  571.     ** during a search or read, the buffer should be re-allocated until it
  572.     **    fits.  Values have a maximum size of 64K, (Streams is an exception to
  573.     **    this and is only limited by disk space.)  If NWDSSearch or NWDSRead
  574.     ** returns ERR_INSUFFICIENT_BUFFER, the buffer should be reallocated and
  575.     **    the search or read attempted again until the buffer reaches a size of
  576.     **    64K. At that point something else must be wrong.
  577.     */
  578.     ccode=NWDSAllocBuf(
  579.         /* size_t    size,                        */ dsHandle->objectInfoSize,     
  580.         /* Buf_T        NWFAR * NWFAR *buf    */ &dsHandle->objectInfo    );
  581.     if(ccode)
  582.         goto Exit1;
  583.     return(dsHandle);
  584.  
  585. Exit1:
  586.     free(dsHandle);
  587. Exit0:
  588.     return(NULL);
  589.     }
  590.  
  591. /*****************************************************************************
  592. **    Syntax:    #include <dsaccess.h>
  593. **
  594. **                NWDSCCODE    DSListSeek(
  595. **                                        DS_HANDLE *dsHandle,
  596. **                                        char *objectName );
  597. ** Parameters:
  598. **                dsHandle
  599. **                    input-takes the search handle returned by a call to
  600. **                            DSSeekOpen.
  601. **
  602. **                objectName
  603. **                    input-specifies which object to read.
  604. **
  605. **    Return Value:
  606. **                DSListSeek returns zero if no error, otherwise returns
  607. **                ccode from the NWDSList call, consult netware error
  608. **                codes for interpretation.
  609. **
  610. **    Remarks:    DSListSeek causes NDS to be queried and receives object names
  611. **                for objects found immediately subordinate to objectName.
  612. **
  613. */
  614. NWDSCCODE    DSListSeek(
  615.                         DS_HANDLE *dsHandle,
  616.                         char *objectName)
  617.     {
  618.     /*-------------------------------------------------------------------------
  619.     ** save this information for future interations of NWDSRead.
  620.     */
  621.     strcpy(dsHandle->baseObjectName,objectName);
  622.     dsHandle->iteration=NO_MORE_ITERATIONS;    /* setup for first NWDSSearch */
  623.     dsHandle->readState=NEW_LIST;
  624.  
  625.     dsHandle->attrNames=NULL;                /* tell DSClose not to try and free this. */
  626.     
  627.     return(_DSList(dsHandle));
  628.     }
  629.  
  630. /*****************************************************************************
  631. ** used in DSReadSeek and DSRead
  632. */
  633. NWDSCCODE    _DSList(DS_HANDLE *dsHandle)
  634.     {
  635.     NWDSCCODE ccode;
  636.     
  637.     ccode=NWDSList(
  638.         /* NWDSContextHandle        context,                */    dsHandle->context,
  639.         /* char        NWFAR *objectName,                */    dsHandle->baseObjectName,
  640.         /* int32        NWFAR *iterationHandle,            */    &dsHandle->iteration,
  641.         /* Buf_T        NWFAR *objectInfo                    */    dsHandle->objectInfo );
  642.  
  643.     return(ccode);            /* normal exit may be an error */
  644.     }
  645.  
  646. /*****************************************************************************
  647. **    Syntax:    #include <dsaccess.h>
  648. **
  649. **                READ_DATA    DSRead(
  650. **                                        DS_HANDLE *dsHandle,
  651. **                                        );
  652. **
  653. **
  654. **    Return Value:
  655. **                EOF    -1 if no data to read.
  656. **                NULL    if critical error occured during call.
  657. **                Pointer to a allocated READ_DATA structure.
  658. **
  659. **    Remarks:
  660. **                DSList is called iteratively until it returns EOF.  DSList
  661. **                allocates and fills a READ_DATA structure with an object,
  662. **                attribute, or attribute value.  READ_DATA strucutures should
  663. **                be freed by a call to the regular free() call. The READ_DATA's
  664. **                readType    indicates what type of information is returned.
  665. **                Possible    data types are OBJECT, ATTR, or ATTR_VALUE for object,
  666. **                attribute or attribute value.  Objects appear before
  667. **                any attributes.  Attributes may appear after an object,
  668. **                attribute or attribute value.  Attribute values appear
  669. **                after attributes or other attribute values.  READ_DATA
  670. **                provides a union that allows for reading the contents
  671. **                respective to their type.  The union fields are selected
  672. **                by addressing the object, attr, and attrVal fields
  673. **                (refer to search.h for a definition of the READ_DATA
  674. **                structure.
  675. **
  676. */
  677. READ_DATA *DSRead(DS_HANDLE *dsHandle)
  678.     {
  679.     READ_DATA *readData;
  680.     NWSIZE    attrValSize;
  681.     NWDSCCODE ccode;
  682.                                   
  683. RE_EVALUATE_SWITCH:
  684.     switch (dsHandle->readState)
  685.         {
  686.         case    NEW_SEARCH:
  687.         case    NEW_LIST:
  688.                 ccode=NWDSGetObjectCount(
  689.                     /* NWDSContextHandle        context,    */    dsHandle->context,
  690.                     /* Buf_T        NWFAR *buf,                */    dsHandle->objectInfo,
  691.                     /* uint32    NWFAR *objectCount    */    &dsHandle->objectCount );
  692.                 if(ccode)
  693.                     goto Exit1;
  694.  
  695.         case    READ_OBJECT_NAME:
  696.             NEXT_READ_OBJECT_NAME:            /* Easy to jump here if no attrValue */
  697.  
  698.             if(dsHandle->objectCount--)
  699.                 {
  700.                 if(NULL==(readData=malloc(sizeof(READ_DATA))))
  701.                     return(NULL);
  702.  
  703.                 ccode=NWDSGetObjectName(
  704.                     /*    NWDSContextHandle        context,        */    dsHandle->context,
  705.                     /*    Buf_T                NWFAR *buf,            */    dsHandle->objectInfo,
  706.                     /*    char                NWFAR *objectName,*/    &readData->read.object.name,
  707.                     /*    uint32            NWFAR *attrCount,    */    &dsHandle->attrCount,
  708.                     /*    Object_Info_T    NWFAR *objectInfo    */    &readData->read.object.objectInfo    );
  709.                 if(ccode)
  710.                     goto Exit1;
  711.             
  712.                 dsHandle->readState=READ_ATTR_NAME;
  713.                 readData->readType=OBJECT;
  714.                 }
  715.             else                /* exit the function EOF meaning no more to read. */
  716.                   {
  717.                 /*----------------------------------------------------------------
  718.                 ** add here iterative NWDSSearch call.
  719.                 */
  720.                 if(NO_MORE_ITERATIONS==dsHandle->iteration)
  721.                     return((void *)EOF);
  722.                 else
  723.                     {
  724.                     switch(dsHandle->handleType)
  725.                         {
  726.                         case DSV_SEARCH:
  727.                             ccode=_DSSearch(dsHandle);
  728.                             dsHandle->readState=NEW_SEARCH;
  729.                             break;
  730.                         case DSV_READ:
  731.                             ccode=_DSRead(dsHandle);
  732.                             dsHandle->readState=NEW_READ;
  733.                             break;
  734.                         case DSV_LIST:
  735.                             ccode=_DSList(dsHandle);
  736.                             dsHandle->readState=NEW_LIST;
  737.                         }
  738.                     if(ccode)
  739.                         return(NULL);
  740.                     else
  741.                         goto RE_EVALUATE_SWITCH;    /* new buffer to get stuff from */
  742.                     }
  743.                 }
  744.             break;
  745.  
  746.         case NEW_READ:
  747.             ccode=NWDSGetAttrCount(
  748.                 /* NWDSContextHandle        context, */ dsHandle->context,
  749.                 /* Buf_T        NWFAR *buf,                */    dsHandle->objectInfo,
  750.                 /* uint32    NWFAR *attrCount        */    &dsHandle->attrCount );
  751.             dsHandle->objectCount=0;    /* read only returns one object name */
  752.  
  753.         case READ_ATTR_NAME:
  754.             
  755.             if(dsHandle->attrCount--)
  756.                 {
  757.                 if(NULL==(readData=malloc(sizeof(READ_DATA))))
  758.                     return(NULL);
  759.             
  760.                 ccode=NWDSGetAttrName(
  761.                     /*    NWDSContextHandle        context,    */    dsHandle->context,
  762.                     /*    Buf_T        NWFAR *buf,                */    dsHandle->objectInfo,
  763.                     /*    char        NWFAR *attrName,        */    &readData->read.attr.name,
  764.                     /*    uint32    NWFAR *attrValCount,    */    &dsHandle->attrValCount,
  765.                     /*    uint32    NWFAR *syntaxID        */    &readData->read.attr.syntaxID);
  766.             
  767.                 if(ccode)
  768.                     goto Exit1;
  769.  
  770.                 dsHandle->syntaxID=readData->read.attr.syntaxID;
  771.                 dsHandle->readState=READ_ATTR_VALUE;
  772.                 readData->readType=ATTR;
  773.                 }
  774.             else
  775.                 goto NEXT_READ_OBJECT_NAME;
  776.  
  777.             break;
  778.  
  779.         case    READ_ATTR_VALUE:
  780.             
  781.             if(dsHandle->attrValCount--)
  782.                 {
  783.                 ccode=NWDSComputeAttrValSize(
  784.                     /* NWDSContextHandle        context,    */    dsHandle->context,      
  785.                     /* Buf_T        NWFAR *buf,                */    dsHandle->objectInfo, 
  786.                     /* uint32    syntaxID,                */    dsHandle->syntaxID,
  787.                     /* uint32    NWFAR *attrValSize    */    &attrValSize    );
  788.                 if(ccode)
  789.                     goto Exit1;
  790.  
  791.                 if(NULL==(readData=malloc(sizeof(READ_DATA)+attrValSize)))
  792.                     return(NULL);
  793.  
  794.                 /*----------------------------------------------------------------
  795.                 ** initialize value to point to attrValue area of buffer.
  796.                 */
  797.                 readData->read.attrVal.value=readData+1;    
  798.  
  799.                 ccode=NWDSGetAttrVal(
  800.                     /*    NWDSContextHandle        context,    */    dsHandle->context,
  801.                     /*    Buf_T        NWFAR *buf,                */    dsHandle->objectInfo,
  802.                     /*    uint32    syntaxID,                */    dsHandle->syntaxID,
  803.                     /*    void        NWFAR *attrVal            */    readData->read.attrVal.value);
  804.  
  805.                 if(ccode)
  806.                     goto    Exit1;
  807.  
  808.                 readData->read.attrVal.syntaxID=dsHandle->syntaxID;
  809.                 readData->readType=ATTR_VALUE;
  810.                 }
  811.             else
  812.                 goto NEXT_READ_OBJECT_NAME;
  813.                 
  814.         }
  815.     return(readData);    /* normal exit */
  816.  
  817. Exit1:                /* critical error exit */
  818.     free(readData);
  819.     return(NULL);
  820.     }
  821.  
  822. /*****************************************************************************
  823. **    Syntax:    #include <dsaccess.h>
  824. **
  825. **                void    DSClose( DS_HANDLE *dsHandle );
  826. **
  827. **
  828. **    Remarks:    Deallocates all memory allocated by DSSearchOpen.
  829. **
  830. */
  831. void DSClose( DS_HANDLE *dsHandle )
  832.     {
  833.     if(DSV_SEARCH == dsHandle->handleType)
  834.         NWDSFreeBuf(dsHandle->filter);
  835.     if(dsHandle->attrNames)
  836.         NWDSFreeBuf(dsHandle->attrNames);
  837.     if(dsHandle->objectInfo)
  838.         NWDSFreeBuf(dsHandle->objectInfo);
  839.     free(dsHandle);
  840.     }
  841.  
  842. /*****************************************************************************
  843. **    Syntax:    prototype in this module.
  844. **
  845. **                NWDSCCODE DSAllocAndInitAttrNamesBuffer(
  846. **                                DS_HANDLE *dsHandle,
  847. **                                char **attrNames);
  848. **
  849. **    Parameters:
  850. **                dsHandle
  851. **                    input/output-Uses handleType to initialize the attrNames
  852. **                            buffer. Stores an attrNames buffer in the handle.
  853. **                            
  854. **                attrNames[]
  855. **                    input-Tells NWDSSearch and NWDSRead what attributes to return
  856. **                            in the objectInfo buffer.  Initialize the last entry
  857. **                            with NULL value to terminate the array.
  858. **
  859. **    Return Value:
  860. **                A completion code which correcponds to any NWDS calls that
  861. **                might have failed.
  862. **
  863. **    Remarks:    DSClose takes care of freeing the attrNames buffer when the handle
  864. **                is closed.
  865. **
  866. */
  867. NWDSCCODE DSAllocAndInitAttrNamesBuffer(DS_HANDLE *dsHandle, char **attrNames)
  868.     {
  869.     NWDSCCODE ccode;
  870.     NWCOUNT    nameCount;
  871.  
  872.     /*-------------------------------------------------------------------------
  873.     ** attrNames specify what attribute names values are wanted to be returned
  874.     **    during a search.  If none are specified DSSearch will return names
  875.     ** for all values.
  876.     */
  877.     if(attrNames)
  878.         {
  879.         for(nameCount=0;attrNames[nameCount];nameCount++);    /* list is delimited by a NULL */
  880.         ccode=NWDSAllocBuf(
  881.             /* size_t    size,                        */ sizeof(NWDS_BUFFER)+MAX_SCHEMA_NAME_CHARS*nameCount, /*room for names*/
  882.             /* Buf_T        NWFAR * NWFAR *buf    */ &dsHandle->attrNames    );
  883.  
  884.         if(ccode)
  885.             goto Exit0;
  886.  
  887.         ccode=NWDSInitBuf(
  888.         /*    NWDSContextHandle        context, */    dsHandle->context,
  889.         /*    uint32    operation,                 */    dsHandle->handleType,
  890.         /*    Buf_T        NWFAR *buf                */    dsHandle->attrNames);
  891.         if(ccode)
  892.             goto Exit1;
  893.  
  894.         /*----------------------------------------------------------------------
  895.         ** put in the return attr names.
  896.         */
  897.         for(nameCount=0;attrNames[nameCount];nameCount++)
  898.             {
  899.             ccode=NWDSPutAttrName(
  900.                 /* NWDSContextHandle        context,    */    dsHandle->context,
  901.                 /* Buf_T        NWFAR *buf,                */    dsHandle->attrNames,
  902.                 /* char        NWFAR *attrName          */    attrNames[nameCount]    );
  903.             if(ccode)
  904.                 goto Exit1;        
  905.             }
  906.         }
  907.     else
  908.         dsHandle->attrNames=NULL;    /* no specified attributes will be used. */
  909.     return(EXIT_SUCCESS);    /* SUCCESS */
  910.  
  911. Exit1:
  912.     NWDSFreeBuf(dsHandle->attrNames);
  913. Exit0:
  914.     return(ccode);
  915.     }
  916.