/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME =  RSMAPIR3.C
 *
 * DESCRIPTIVE NAME =  Resource Management Driver - Services for Ring 3 Clients
 *
 *
 *
 * VERSION = V1.01
 *
 * DATE
 *
 * DESCRIPTION :
 *
 * Purpose:
 *
 *
 *
 * FUNCTIONS  :
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 *
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define  INCL_NOBASEAPI
#define  INCL_NOPMAPI
#define  INCL_DOSERRORS
#include <os2.h>

#include <dskinit.h>
#include <devcmd.h>

#include "dhcalls.h"

#include "strat2.h"
#include "scsi.h"
#include "reqpkt.h"

#define RMCode SwapCode
#include "rmioctl.h"
#include "rmcalls.h"

#include "rsmcons.h"
#include "rsmtypes.h"
#include "rsmproto.h"
#include "rsmextrn.h"



/*------------------------------------------------------------------------*/
/*                                                                        */
/* Resource Manager - Serices for Ring 3 Clients                          */
/*                                                                        */
/*------------------------------------------------------------------------*/


/*------------------------------------*/
/* RMStrat1                           */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/

VOID NEAR RMStrat1()
{
  PRPH pRPH;
  USHORT        Cmd;

  _asm
  {
    mov word ptr pRPH[0], bx
    mov word ptr pRPH[2], es
  }

  pRPH->Status = STATUS_DONE;
  Cmd = pRPH->Cmd;

  if ( Cmd == CMDInitBase )
  {
    RMInit( (PRPINITIN) pRPH );
  }
  else if ( Cmd == CMDGenIOCTL )
  {
    RMIOCtl( pRPH );
  }
  else
  {
    StatusError( pRPH, STATUS_DONE | STATUS_ERR_UNKCMD );
  }

  _asm
  {
    leave
    retf
  }

}

/*------------------------------------*/
/* RMIOCtl                            */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/

VOID FAR RMIOCtl( PRPH pRPH )
{
PRP_GENIOCTL pRP = (PRP_GENIOCTL)pRPH;

  if ( RMEntry() ) {
     StatusError( pRPH, STATUS_DONE | STATUS_ERR_UNKCMD );
     return;
  }

  if (pRP->Category == CAT_RM) {
     switch (pRP->Function){
        case FUNC_RM_GET_NODEINFO:
           RMGetNodeInfoIOCtl( pRP );
           break;

        case FUNC_RM_ENUM_NODES:
           RMEnumNodeIOCtl( pRP );
           break;

        case FUNC_RM_BASEDEV_INIT:
        case FUNC_RM_BASEDEV_FAIL:
        case FUNC_RM_BASEDEV_LOAD:
        case FUNC_RM_DEVICE_INIT:
        case FUNC_RM_DEVICE_FAIL:
        case FUNC_RM_DEVICE_LOAD:
           RMKrnlIOCtl( pRP );
           break;


        default:
           StatusError( pRPH, STATUS_DONE | STATUS_ERR_UNKCMD );
           return;
     }
  } else {
     StatusError( pRPH, STATUS_DONE | STATUS_ERR_UNKCMD );
  }

  RMExit();

}

/*------------------------------------*/
/* StatusError                        */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/

VOID FAR StatusError(PRPH pRPH, USHORT ErrorCode )
{
  pRPH->Status = ErrorCode;
  return;
}

/*------------------------------------*/
/* RMEnumNodeIOCtl                    */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMEnumNodeIOCtl(PRP_GENIOCTL pRP)
{
PRM_ENUMNODES_PARM   pParm = (PRM_ENUMNODES_PARM)pRP->ParmPacket;
PRM_ENUMNODES_DATA   pData = (PRM_ENUMNODES_DATA)pRP->DataPacket;
PNODEENTRY           pNodeEntry;
USHORT               NeededSize;
USHORT               cEntries;
USHORT               rc;


   /*---------------------------------*/
   /* Validate Parm and Data Packets  */
   /*---------------------------------*/

  if ((pParm==NULL) || (pData == NULL)){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

   /*---------------------------------*/
   /* Verify Parm Buffer Access       */
   /*---------------------------------*/

  NeededSize = ( sizeof(RM_ENUMNODES_PARM));

  if (pRP->ParmLen < NeededSize){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

  rc = DevHelp_VerifyAccess( SELECTOROF(pParm),
                             NeededSize,
                             OFFSETOF(pParm),
                             VERIFY_READONLY);

  if (rc){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

   /*---------------------------------*/
   /* Verify Data Buffer Access       */
   /*   if fails try to fill in       */
   /* NumEntries field                */
   /*---------------------------------*/

  switch (pParm->Command) {
     case RM_COMMAND_PHYS:
        cEntries = cRMNodes;
        break;

     case RM_COMMAND_LOG:
        cEntries = cRMLNodes;
        break;

     case RM_COMMAND_DRVR:
        cEntries =  cRMDrvrNodes + cRMNodes + cRMLNodes;
        break;

     default:
        StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
        return;
  }

  NeededSize = ( sizeof(ULONG) + ( cEntries * sizeof(NODEENTRY)) );

  /*---------------------------------*/
  /* Number of Entries in array      */
  /*---------------------------------*/

  if (!DevHelp_VerifyAccess( SELECTOROF(pData),
                             sizeof(ULONG),
                             OFFSETOF(pData),
                             VERIFY_READWRITE)){
     pData->NumEntries = cEntries;
  }


  if (pRP->DataLen < NeededSize){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

  /*---------------------------------*/
  /* If cannot access - error        */
  /*---------------------------------*/

  if(DevHelp_VerifyAccess( SELECTOROF(pData),
                             NeededSize,
                             OFFSETOF(pData),
                             VERIFY_READWRITE)){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

   /*--------------------*/
   /* Get first entry    */
   /*--------------------*/

  pNodeEntry = (PNODEENTRY)&pData->NodeEntry;

   /*---------------------------------*/
   /* Go forth and Enumerate          */
   /*---------------------------------*/

  switch (pParm->Command){
     case RM_COMMAND_PHYS:
        RMGetEnumEntry(PDevPtrs[PDEV_ROOT],
                       ((PNODEENTRY FAR *)&pNodeEntry),
                       BASE_DEPTH);
        break;

     case RM_COMMAND_LOG:
        RMGetEnumEntry(LDevPtrs[LDEV_CLASS_ROOT],
                       ((PNODEENTRY FAR *)&pNodeEntry),
                       BASE_DEPTH);
        break;

     case RM_COMMAND_DRVR:
        RMGetDrvrEnumEntry((PDRVRNODE) PDevPtrs[PDEV_RMDD],
                           ((PNODEENTRY FAR *)&pNodeEntry),
                           BASE_DEPTH);
        break;

     default:
        StatusError( (PRPH)pRP, STATUS_DONE | STATUS_ERR_UNKCMD );
        return;
  }
}

/*-------------------------------------*/
/* RMGetEnumEntry                      */
/*   Recursive Enumeration of RMNodes  */
/*                                     */
/*                                     */
/*-------------------------------------*/

VOID NEAR RMGetEnumEntry(PRMNODE pRMNode, PNODEENTRY FAR *ppNodeEntry, USHORT Depth)
{

   /*------------------*/
   /* Fill in my Entry */
   /*------------------*/

   (*ppNodeEntry)->RMHandle   = (RMHANDLE)RMMAKEHANDLE(pRMNode);
   (*ppNodeEntry)->Depth      = (ULONG)Depth;

   /*-----------------------*/
   /* Increment Array Index */
   /*-----------------------*/

   (*ppNodeEntry)++;

   /*--------------------*/
   /* Enumerate Children */
   /*--------------------*/

   if (pRMNode->pDevChild)
     RMGetEnumEntry(pRMNode->pDevChild, ppNodeEntry, Depth+1);

   /*--------------------*/
   /* Enumerate Siblings */
   /*--------------------*/

   if (pRMNode->pDevSibling)
     RMGetEnumEntry(pRMNode->pDevSibling, ppNodeEntry, Depth);

   return;
}


/*-------------------------------------*/
/* RMGetDrvrEnumEntry                  */
/*   Enumeration of Driver Nodes       */
/*                                     */
/*                                     */
/*-------------------------------------*/

VOID NEAR RMGetDrvrEnumEntry(PDRVRNODE pDrvrNode, PNODEENTRY FAR *ppNodeEntry, USHORT Depth)
{
PRMNODE pDevChain;


   /*------------------*/
   /* Fill in my Entry */
   /*------------------*/

   (*ppNodeEntry)->RMHandle = (RMHANDLE)RMMAKEHANDLE(pDrvrNode);
   (*ppNodeEntry)->Depth      = (ULONG)Depth;

   /*-----------------------*/
   /* Increment Array Index */
   /*-----------------------*/

   (*ppNodeEntry)++;


   /*--------------------*/
   /* Enumerate Children */
   /*--------------------*/
   pDevChain = pDrvrNode->pDevChain;

   while( pDevChain ) {
      (*ppNodeEntry)->RMHandle = (RMHANDLE)RMMAKEHANDLE(pDevChain);
      (*ppNodeEntry)->Depth    = (ULONG)Depth + 1;


      (*ppNodeEntry)++;
      pDevChain = pDevChain->pDevDrvChain;
   }


   /*--------------------*/
   /* Enumerate Siblings */
   /*--------------------*/

   if (pDrvrNode->pDrvSibling)
     RMGetDrvrEnumEntry(pDrvrNode->pDrvSibling, ppNodeEntry, Depth);

   return;
}


/*------------------------------------*/
/* RMGetNodeInfoIOCtl                 */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMGetNodeInfoIOCtl(PRP_GENIOCTL pRP)
{
PRM_GETNODE_PARM   pParm = (PRM_GETNODE_PARM)pRP->ParmPacket;
PRM_GETNODE_DATA   pData = (PRM_GETNODE_DATA)pRP->DataPacket;
PRM_NODE           pNodeInfo;          /* Ring 3 Super Node             */
PRMNODE            pRMNode;            /* Copy From this RMNode         */
PDRVRNODE          pDrvrNode;          /* Copy From this DrvrNode       */
PRESNODE           pResChain;          /* Copy From this Resource Chain */
PUCHAR             pCurrent;           /* Pointer to start of free      */
USHORT             NeededSize;         /* Minimum buffer size           */
USHORT             rc;


   /*---------------------------------*/
   /* Validate Parm and Data Packets  */
   /*---------------------------------*/

  if ((pParm==NULL) || (pData == NULL)){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

   /*---------------------------------*/
   /* Verify Parm Buffer Access       */
   /*---------------------------------*/

  NeededSize = ( sizeof(RM_GETNODE_PARM));

  if (pRP->ParmLen < NeededSize){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

  rc = DevHelp_VerifyAccess( SELECTOROF(pParm),
                             NeededSize,
                             OFFSETOF(pParm),
                             VERIFY_READONLY);

  if (rc){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

   /*---------------------------------*/
   /* Verify Data Buffer Access       */
   /*   if fails try to fill in       */
   /* NumEntries field                */
   /*---------------------------------*/


  NeededSize = RMCalcNodeInfoSize( pParm->RMHandle );

  /*---------------------------*/
  /* Size of Node Info         */
  /*---------------------------*/

  if (!DevHelp_VerifyAccess( SELECTOROF(pData),
                             sizeof(ULONG),
                             OFFSETOF(pData),
                             VERIFY_READWRITE)){
     pData->RMNodeSize = NeededSize;
  }


  if (pRP->DataLen < NeededSize){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

  /*---------------------------------*/
  /* If cannot access - error        */
  /*---------------------------------*/

  if (DevHelp_VerifyAccess( SELECTOROF(pData),
                             NeededSize,
                             OFFSETOF(pData),
                             VERIFY_READWRITE)){
     StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
     return;
  }

   /*--------------------*/
   /* Get first entry    */
   /*--------------------*/

  pNodeInfo = (PRM_NODE)&pData->RMNode;



   /*-------------------------------------*/
   /* Get pointer to RMNode               */
   /*  or DriverNode                      */
   /*-------------------------------------*/

  if ((pRMNode = RMNodeFromHandle( pParm->RMHandle, ANY_COOKIE)) == NULL){
     if ((pRMNode = (PRMNODE)pDrvrNode = RMNodeFromHandle( pParm->RMHandle, DRIVER_NODE_COOKIE)) == NULL){
        StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
        return;
     }
  }

   /*--------------------------------------------*/
   /* Fill in Node Info Version                  */
   /*--------------------------------------------*/

  pNodeInfo->VersionInfo = (CMVERSION_MAJOR * 100) + (CMVERSION_MINOR);

   /*--------------------------------------------*/
   /* Point to bottom of Base Node Info          */
   /*--------------------------------------------*/


  pCurrent = (PUCHAR)pNodeInfo + sizeof(RM_NODE);


   /*-----------------------------*/
   /* Copy RMNode Structure       */
   /*-----------------------------*/

  pNodeInfo->pAdapterNode = (PADAPTERSTRUCT)pCurrent;
  switch (pRMNode->Cookie){
     case ADAPTER_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_ADAPTER;
        pDrvrNode=pRMNode->pDriver;
        RMCopyAdapter((PUCHAR FAR *)&pCurrent, pRMNode->pAdpt);
        break;
     case DEVICE_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_DEVICE;
        pDrvrNode=pRMNode->pDriver;
        RMCopyDevice((PUCHAR FAR*)&pCurrent, pRMNode->pDev);
        break;
     case DRIVER_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_DRIVER;
        RMCopyDriver((PUCHAR FAR*)&pCurrent, pDrvrNode->pDrv);
        break;
     case LDEV_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_LDEV;
        pDrvrNode=pRMNode->pDriver;
        RMCopyLDev((PUCHAR FAR*)&pCurrent, pRMNode->pLDev);
        break;
     case SYS_NODE_COOKIE:
        pNodeInfo->NodeType = RMTYPE_SYSNAME;
        pDrvrNode=pRMNode->pDriver;
        RMCopySysName((PUCHAR FAR*)&pCurrent, pRMNode->pSysDev);
        break;
     default:
        StatusError( (PRPH)pRP, STATUS_DONE | STATUS_GEN_ERR );
        return;
  }

  pNodeInfo->DriverHandle = RMMAKEHANDLE( pDrvrNode );


   /*-----------------------------*/
   /* Copy Resource Structures    */
   /*-----------------------------*/

   if ( !((pNodeInfo->NodeType == RMTYPE_LDEV   ) ||
          (pNodeInfo->NodeType == RMTYPE_SYSNAME))  ) {

      if (pNodeInfo->NodeType == RMTYPE_DRIVER)
         pResChain = pDrvrNode->pResChain;
      else
         pResChain = pRMNode->pResChain;

   } else {
      pResChain=NULL;
   }

   /*---------------------------------------------*/
   /* This is wrong! but I'm trying to fix rmview */
   /*---------------------------------------------*/

   pNodeInfo->pResourceList = (PRESOURCELIST)pCurrent;
   RMCopyResources((PUCHAR FAR *)&pCurrent, pResChain);

   /*------------------------------*/
   /* Fix up Ring 3 pointers       */
   /*------------------------------*/


   RMFixNodeInfoPointers( pNodeInfo );


   return;
}


/*------------------------------------*/
/* RMCalcNodeInfoSize                 */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/

USHORT      NEAR RMCalcNodeInfoSize( RMHANDLE RMHandle)
{
   return MAX_RM_NODE_SIZE;
}


/*------------------------------------*/
/* RMCopyAdapter                      */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMCopyAdapter(PUCHAR FAR *ppBuffer, PADAPTERSTRUCT pAS)
{
  RMCopyStdNode( ppBuffer, ADAPTER_NODE_COOKIE, pAS );
}

/*------------------------------------*/
/* RMCopyDevice                       */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMCopyDevice(PUCHAR FAR *ppBuffer, PDEVICESTRUCT pDS)
{
  RMCopyStdNode( ppBuffer, DEVICE_NODE_COOKIE, pDS );
}

/*------------------------------------*/
/* RMCopyStdNode                      */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/

VOID NEAR RMCopyStdNode(PUCHAR FAR *ppBuffer, ULONG NodeCookie, PVOID pDS )
{
PBYTE            pNewDev;
PADJUNCT         pAdj;
PADJUNCT         pAdjunct;
PADJUNCT         pPrevAdj;
PADJUNCT         pAdjList;
PADJUNCT         FAR *ppAdjPtr;
USHORT           TextLen=0;
USHORT           StructLen;
PSZ              pDescName;
PSZ              FAR *ppDescPtr;

   /*-----------------------------*/
   /* Start of Free Space         */
   /*-----------------------------*/

   pNewDev = *ppBuffer;

  switch ( NodeCookie )
  {
     case ADAPTER_NODE_COOKIE:
       pAdjunct  = ((PADAPTERSTRUCT) pDS)->pAdjunctList;
       pDescName = ((PADAPTERSTRUCT) pDS)->AdaptDescriptName;
       ppAdjPtr  = &(((PADAPTERSTRUCT) pNewDev)->pAdjunctList);
       ppDescPtr = &(((PADAPTERSTRUCT) pNewDev)->AdaptDescriptName);
       StructLen = sizeof(ADAPTERSTRUCT);
       break;
     case DEVICE_NODE_COOKIE:
       pAdjunct  = ((PDEVICESTRUCT) pDS)->pAdjunctList;
       pDescName = ((PDEVICESTRUCT) pDS)->DevDescriptName;
       ppAdjPtr  = &(((PDEVICESTRUCT) pNewDev)->pAdjunctList);
       ppDescPtr = &(((PDEVICESTRUCT) pNewDev)->DevDescriptName);
       StructLen = sizeof(DEVICESTRUCT);
       break;
     case LDEV_NODE_COOKIE:
       pAdjunct  = ((PLDEVSTRUCT) pDS)->pAdjunctList;
       pDescName = ((PLDEVSTRUCT) pDS)->LDevDescriptName;
       ppAdjPtr  = &(((PLDEVSTRUCT) pNewDev)->pAdjunctList);
       ppDescPtr = &(((PLDEVSTRUCT) pNewDev)->LDevDescriptName);
       StructLen = sizeof(LDEVSTRUCT);
       break;
     case SYS_NODE_COOKIE:
       pAdjunct  = ((PSYSNAMESTRUCT) pDS)->pAdjunctList;
       pDescName = ((PSYSNAMESTRUCT) pDS)->SysDescriptName;
       ppAdjPtr  = &(((PSYSNAMESTRUCT) pNewDev)->pAdjunctList);
       ppDescPtr = &(((PSYSNAMESTRUCT) pNewDev)->SysDescriptName);
       StructLen = sizeof(SYSNAMESTRUCT);
       break;
     default:
       _asm int 3
       break;
  }


   memcpy( pNewDev, pDS, StructLen);


   /*----------------------------------*/
   /* Transfer Adjunct list structures */
   /*----------------------------------*/


   pAdj = (PADJUNCT)(pNewDev + StructLen);
   if ( pAdjunct )
   {
      for ( pAdjList=pAdjunct;
            pAdjList;
            pAdjList=pAdjList->pNextAdj )
      {
        memcpy( pAdj, pAdjList, pAdjList->AdjLength );

        pAdj->pNextAdj = (PADJUNCT)((PBYTE)pAdj + pAdjList->AdjLength);

        pPrevAdj = pAdj;
        pAdj     = pAdj->pNextAdj;
      }

      pPrevAdj->pNextAdj  = NULL;
      *ppAdjPtr = (PADJUNCT)(pNewDev + StructLen);
   }


   /*----------------------------------*/
   /* Transfer DevDescription Text     */
   /*----------------------------------*/

   TextLen=strlen(pDescName)+1;
   *ppDescPtr = (PSZ) pAdj;
   memcpy( pAdj, pDescName, TextLen );

   *ppBuffer = (PUCHAR)pAdj + TextLen;

}

/*------------------------------------*/
/* RMCopyDriver                       */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMCopyDriver(PUCHAR FAR *ppBuffer, PDRIVERSTRUCT pDS)
{
PDRIVERSTRUCT    pNewDrvr;
USHORT           TextLen=0;
PSZ              pString;



   /*-----------------------------*/
   /* Start of Free Space         */
   /*-----------------------------*/

   pNewDrvr = (PDRIVERSTRUCT)*ppBuffer;

   memcpy( pNewDrvr, pDS, sizeof(DRIVERSTRUCT));


   /*----------------------------------*/
   /* Transfer DrvrDescript Text       */
   /*----------------------------------*/
   pString = (PSZ)(pNewDrvr + 1);

   TextLen=strlen(pDS->DrvrName)+1;
   pNewDrvr->DrvrName = (PSZ) pString;
   memcpy( pString, pDS->DrvrName, TextLen );
   pString += TextLen;

   TextLen=strlen(pDS->DrvrDescript)+1;
   pNewDrvr->DrvrDescript = (PSZ) pString;
   memcpy( pString, pDS->DrvrDescript, TextLen );
   pString += TextLen;

   TextLen=strlen(pDS->VendorName)+1;
   pNewDrvr->VendorName = (PSZ) pString;
   memcpy( pString, pDS->VendorName, TextLen );
   pString += TextLen;

   *ppBuffer = (PUCHAR)pString + TextLen;

}

/*------------------------------------*/
/* RMCopyResources                    */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMCopyResources(PUCHAR FAR *ppBuffer, PRESNODE pResNode)
{
PRESOURCELIST       pResList;
PRESOURCESTRUCT     pNewRes;
PRESOURCESTRUCT     pOldRes;
USHORT              ResCount=0;


   /*-----------------------------*/
   /* Start of Free Space         */
   /*-----------------------------*/
   pResList = (PRESOURCELIST)*ppBuffer;
   pNewRes  = &pResList->Resource[0];

   pOldRes = (pResNode) ?
             (PRESOURCESTRUCT)&pResNode->NodeData :
             NULL;

   while (pOldRes) {
      memcpy( pNewRes, pResNode->NodeData, sizeof(RESOURCESTRUCT));
      pNewRes++;                              /* Start of free */
      ResCount++;                             /* up count      */
      pResNode = pResNode->pResDevChain;      /* next ResNode  */
      pOldRes  = (PRESOURCESTRUCT)(pResNode ? pResNode->pIO : NULL);
   }

   pResList->Count = ResCount;
   *ppBuffer = (PUCHAR)pNewRes;

}

/*------------------------------------*/
/* RMCopyLDev                         */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMCopyLDev(PUCHAR FAR *ppBuffer, PLDEVSTRUCT pLS)
{
  RMCopyStdNode( ppBuffer, LDEV_NODE_COOKIE, pLS );
}

/*------------------------------------*/
/* RMCopySysName                      */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMCopySysName(PUCHAR FAR *ppBuffer, PSYSNAMESTRUCT pSS)
{
  RMCopyStdNode( ppBuffer, SYS_NODE_COOKIE, pSS );
}


/*------------------------------------*/
/* RMFixNodeInfoPointers              */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMFixNodeInfoPointers(PRM_NODE pNodeInfo)
{
LIN LinBase;
PADAPTERSTRUCT pAdpt;
PDEVICESTRUCT  pDev;

   /*--------------------------------------------*/
   /* Get Linear Pointer to stick into structure */
   /*--------------------------------------------*/

  if (DevHelp_VirtToLin( SELECTOROF(pNodeInfo),
                         OFFSETOF(pNodeInfo),
                         &LinBase)){
     return;
  }




  switch (pNodeInfo->NodeType){
     case ( RMTYPE_ADAPTER ):
        RMFixAdapterPointers( pNodeInfo, LinBase );
        break;
     case ( RMTYPE_DEVICE ):
        RMFixDevicePointers( pNodeInfo, LinBase );
        break;
     case ( RMTYPE_DRIVER ):
        RMFixDriverPointers( pNodeInfo, LinBase );
        break;
     case ( RMTYPE_LDEV ):
        RMFixLDevPointers( pNodeInfo, LinBase );
        break;
     case ( RMTYPE_SYSNAME ):
        RMFixSysNamePointers( pNodeInfo, LinBase );
        break;
     default:
        break;
   }


   if( pNodeInfo->pResourceList){
      pNodeInfo->pResourceList = (PRESOURCELIST)RMMAKELINEAR( pNodeInfo->pResourceList);
   }

}


/*------------------------------------*/
/* RMFixAdapterPointers               */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMFixAdapterPointers(PRM_NODE pNodeInfo, LIN LinBase)
{
PADAPTERSTRUCT  pAdpt;
PADJUNCT        pAdj;
PADJUNCT        pNextAdj;                                           /*@V107246*/

  pAdpt=pNodeInfo->pAdapterNode;
  pNodeInfo->pAdapterNode = (PADAPTERSTRUCT)RMMAKELINEAR( pNodeInfo->pAdapterNode );

  pAdpt->AdaptDescriptName = (PSZ)RMMAKELINEAR( pAdpt->AdaptDescriptName );


  pAdj = pAdpt->pAdjunctList;

  if(pAdj) {
     pAdpt->pAdjunctList = (PADJUNCT)RMMAKELINEAR( pAdpt->pAdjunctList );

     while(pAdj->pNextAdj){
        pNextAdj=pAdj->pNextAdj;                                    /*@V107246*/
        pAdj->pNextAdj = (PADJUNCT)RMMAKELINEAR( pAdj->pNextAdj );
        pAdj=pNextAdj;
     }                                                              /*@V107246*/
  }



}

/*------------------------------------*/
/* RMFixDevicePointers                */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMFixDevicePointers(PRM_NODE pNodeInfo, LIN LinBase)
{
PDEVICESTRUCT   pDev;
PADJUNCT        pAdj;
PADJUNCT        pNextAdj;                                           /*@V103757*/

  pDev=pNodeInfo->pDeviceNode;
  pNodeInfo->pDeviceNode = (PDEVICESTRUCT)RMMAKELINEAR( pNodeInfo->pDeviceNode );

  pDev->DevDescriptName = (PSZ)RMMAKELINEAR( pDev->DevDescriptName );

  pAdj = pDev->pAdjunctList;

  if(pAdj) {
     pDev->pAdjunctList = (PADJUNCT)RMMAKELINEAR( pDev->pAdjunctList );

     while(pAdj->pNextAdj){
        pNextAdj=pAdj->pNextAdj;                                    /*@V103757*/
        pAdj->pNextAdj = (PADJUNCT)RMMAKELINEAR( pAdj->pNextAdj );
        pAdj=pNextAdj;
     }                                                              /*@V103757*/

  }

}


/*------------------------------------*/
/* RMFixDriverPointers                */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMFixDriverPointers(PRM_NODE pNodeInfo, LIN LinBase)
{
PDRIVERSTRUCT  pDrvr;

  pDrvr=pNodeInfo->pDriver;
  pNodeInfo->pDriver = (PDRIVERSTRUCT)RMMAKELINEAR( pNodeInfo->pDriver );

  pDrvr->DrvrName         = (PSZ)RMMAKELINEAR( pDrvr->DrvrName );
  pDrvr->DrvrDescript     = (PSZ)RMMAKELINEAR( pDrvr->DrvrDescript );
  pDrvr->VendorName       = (PSZ)RMMAKELINEAR( pDrvr->VendorName );

}


/*------------------------------------*/
/* RMFixLDevPointers                  */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMFixLDevPointers(PRM_NODE pNodeInfo, LIN LinBase)
{
PLDEVSTRUCT     pLDev;
PADJUNCT        pAdj;
PADJUNCT        pNextAdj;                                           /*@V103757*/

  pLDev=pNodeInfo->pLDevNode;
  pNodeInfo->pLDevNode = (PLDEVSTRUCT)RMMAKELINEAR( pNodeInfo->pLDevNode );

  pLDev->LDevDescriptName = (PSZ)RMMAKELINEAR( pLDev->LDevDescriptName );

  pAdj = pLDev->pAdjunctList;

  if(pAdj) {
     pLDev->pAdjunctList = (PADJUNCT)RMMAKELINEAR( pLDev->pAdjunctList );

     while(pAdj->pNextAdj){
        pNextAdj=pAdj->pNextAdj;                                    /*@V103757*/
        pAdj->pNextAdj = (PADJUNCT)RMMAKELINEAR( pAdj->pNextAdj );
        pAdj=pNextAdj;                                              /*@V013757*/
     }
  }

}
/*------------------------------------*/
/* RMFixSysNamePointers               */
/*                                    */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMFixSysNamePointers(PRM_NODE pNodeInfo, LIN LinBase)
{
PSYSNAMESTRUCT  pSys;
PADJUNCT        pAdj;
PADJUNCT        pNextAdj;                                           /*@V103757*/

  pSys=pNodeInfo->pSysNameNode;
  pNodeInfo->pSysNameNode = (PSYSNAMESTRUCT)RMMAKELINEAR( pNodeInfo->pSysNameNode );

  pSys->SysDescriptName = (PSZ)RMMAKELINEAR( pSys->SysDescriptName );

  pAdj = pSys->pAdjunctList;

  if(pAdj) {
     pSys->pAdjunctList = (PADJUNCT)RMMAKELINEAR( pSys->pAdjunctList );

     while(pAdj->pNextAdj){
        pNextAdj=pAdj->pNextAdj;                                    /*@V103757*/
        pAdj->pNextAdj = (PADJUNCT)RMMAKELINEAR( pAdj->pNextAdj );
        pAdj=pNextAdj;                                              /*@V103757*/
     }
  }

}

/*------------------------------------*/
/* RMKrnlIOCtl                        */
/*    Krnl notifications              */
/*                                    */
/*                                    */
/*------------------------------------*/


VOID NEAR RMKrnlIOCtl(PRP_GENIOCTL pRP)
{

PSZ      pDriverName      = (PSZ)pRP->ParmPacket;
USHORT   Func             = (USHORT)pRP->Function;


   /*---------------------------------*/
   /* Validate Parm Packets           */
   /*---------------------------------*/

  if (pDriverName==NULL)
     return;

  switch (Func){
     case FUNC_RM_BASEDEV_INIT:
     case FUNC_RM_DEVICE_INIT:
        DriverState |= DRIVER_INIT;
        break;


     case FUNC_RM_BASEDEV_LOAD:
     case FUNC_RM_DEVICE_LOAD:

        if (DriverState & DRIVER_CREATED){
           DriverState = DRIVER_NONE_CURRENT;
           return;
        } else if (Func == FUNC_RM_BASEDEV_LOAD) {
           DummyDriver.DrvrDescript = DummyBasedevTxt;
        } else {
           DummyDriver.DrvrDescript = DummyDeviceTxt;
        }
        DriverState = DRIVER_NONE_CURRENT;

        DummyDriver.DrvrName = pDriverName;

        RMCreateDriverNode(&DummyDriver);

        break;

     case FUNC_RM_BASEDEV_FAIL:
     case FUNC_RM_DEVICE_FAIL:
        /* Don't care currently */
        break;
  }

  return;
}
