⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 functions.c

📁 This the third edition of the Writing Device Drivers articles. The first article helped to simply ge
💻 C
📖 第 1 页 / 共 5 页
字号:
    NTSTATUS NtStatus;

    *pdwStringLength = 0;

    /*
     * We want to acquire the instance mutex so we can manipulate the buffer indepdent of other
     * threads (in our process and other processes).
     * 
     * We want to wait so that we cannot be interrupted and we will not wake up to process APC's.
     *
     */
    
    NtStatus = KeWaitForMutexObject(&pExampleList->kInstanceBufferMutex, Executive, KernelMode, FALSE, NULL);

    if(NT_SUCCESS(NtStatus))
    {
        DbgPrint("Start Index = %i Stop Index = %i Size Of Buffer = %i\n", pExampleList->uiStartIndex, pExampleList->uiStopIndex, sizeof(pExampleList->pCircularBuffer));
        /*
         * To copy the buffer created in user mode to the kernel buffer we need to determine
         * where the circular buffer pointers are.
         *
         *  [*****              ************************]
         *     Stop           Start
         * 
         * If the Start index is farther than the Stop index then we can assume that memory from the Start to the
         * index (including wrapping).  So Start - (Stop + 1) = Valid Length.  We want to add 1 to the Stop index 
         * so that we do not get Start == Stop since this is reserved for empty buffer.
         *
         */

       DbgPrint("Example_WriteData = %i > %i\n", pExampleList->uiStartIndex, (pExampleList->uiStopIndex + 1));
       if(pExampleList->uiStartIndex > (pExampleList->uiStopIndex + 1))
       {
          UINT uiCopyLength = MIN((pExampleList->uiStartIndex - (pExampleList->uiStopIndex + 1)), uiLength);
          
          DbgPrint("uiCopyLength = %i (%i, %i)\n", uiCopyLength, (pExampleList->uiStartIndex - (pExampleList->uiStopIndex + 1)), uiLength);

          if(uiCopyLength)
          {
              RtlCopyMemory(pExampleList->pCircularBuffer + pExampleList->uiStopIndex, pData, uiCopyLength);

              pExampleList->uiStopIndex += uiCopyLength;
              *pdwStringLength =  uiCopyLength;

              bDataWritten = TRUE;
          }
       }
       else
       {
           UINT uiLinearLengthAvailable;
           UINT uiCopyLength;

            /*
             * To copy the buffer created in user mode to the kernel buffer we need to determine
             * where the circular buffer pointers are.
             *
             *  [    ****************                     ]
             *     Start           Stop
             * 
             * If the Start index is before the Stop Index we can assume that the memory from the Start index
             * to the STop Index is full.  Thus, we first want to copy linear memory from the stop index
             * to the end of the buffer.
             *
             * To complicate matters, we don't want Start == Stop since this will signify an empty buffer in our
             * simple example.  So, what we do is that if the Start Index == 0, instead of using
             * buffer size - Stop Index and wrapping the Stop Index we simply add 1 to Stop Index so that we
             * get a smaller area and we won't wrap around.
             *
             */
           if(pExampleList->uiStartIndex <= pExampleList->uiStopIndex)
           {
           
               if(pExampleList->uiStartIndex == 0)
               {
                   uiLinearLengthAvailable = sizeof(pExampleList->pCircularBuffer) - (pExampleList->uiStopIndex + 1);
               }
               else
               {
                   uiLinearLengthAvailable = sizeof(pExampleList->pCircularBuffer) - pExampleList->uiStopIndex;
               }
    
               uiCopyLength = MIN(uiLinearLengthAvailable, uiLength);
    
               DbgPrint("uiCopyLength %i = MIN(uiLinearLengthAvailable %i, uiLength %i)\n", uiCopyLength, uiLinearLengthAvailable, uiLength);
    
               if(uiCopyLength)
               {
                   RtlCopyMemory(pExampleList->pCircularBuffer + pExampleList->uiStopIndex, pData, uiCopyLength);
    
                   pExampleList->uiStopIndex += uiCopyLength;
                   *pdwStringLength =  uiCopyLength;
    
                   bDataWritten = TRUE;
    
                   if(pExampleList->uiStopIndex == sizeof(pExampleList->pCircularBuffer))
                   {
                      pExampleList->uiStopIndex = 0;
    
                      DbgPrint("pExampleList->uiStopIndex = 0 %i - %i = %i\n", uiLength , uiCopyLength, (uiLength - uiCopyLength));
    
                      if((uiLength - uiCopyLength) > 0)
                      {
                          UINT uiSecondCopyLength = MIN(pExampleList->uiStartIndex - (pExampleList->uiStopIndex + 1), uiLength - uiCopyLength);
                          
                          DbgPrint("uiSecondCopyLength = 0 %i\n", uiSecondCopyLength);
    
                          if(uiSecondCopyLength)
                          {
                             RtlCopyMemory(pExampleList->pCircularBuffer + pExampleList->uiStopIndex, pData, uiSecondCopyLength);
    
                             pExampleList->uiStopIndex += uiSecondCopyLength;
                             *pdwStringLength =  uiCopyLength + uiSecondCopyLength;
    
                             bDataWritten = TRUE;
                          }
    
                      }
                   }
    
               }
           }
       }
        
       DbgPrint("Start Index = %i Stop Index = %i Size Of Buffer = %i\n", pExampleList->uiStartIndex, pExampleList->uiStopIndex, sizeof(pExampleList->pCircularBuffer));

       KeReleaseMutex(&pExampleList->kInstanceBufferMutex, FALSE);
    }

    return bDataWritten;
}

/**********************************************************************
 * 
 *  Example_ReadData
 *
 *    This is called to read data from the circular buffer.
 *    This function does not block and will not wait for data, so
 *    no data will simply fail this call.  If any data at all 
 *    is read then we will return success with the number of bytes
 *    read.
 *
 **********************************************************************/
BOOLEAN Example_ReadData(PEXAMPLE_LIST pExampleList, PCHAR pData, UINT uiLength, UINT *pdwStringLength)
{
    BOOLEAN bDataRead = FALSE;
    NTSTATUS NtStatus;

    *pdwStringLength = 0;

    /*
     * We want to acquire the instance mutex so we can manipulate the buffer indepdent of other
     * threads (in our process and other processes).
     * 
     * We want to wait so that we cannot be interrupted and we will not wake up to process APC's.
     *
     */
    
    NtStatus = KeWaitForMutexObject(&pExampleList->kInstanceBufferMutex, Executive, KernelMode, FALSE, NULL);

    if(NT_SUCCESS(NtStatus))
    {
        DbgPrint("Start Index = %i Stop Index = %i Size Of Buffer = %i\n", pExampleList->uiStartIndex, pExampleList->uiStopIndex, sizeof(pExampleList->pCircularBuffer));
        /*
         * To copy the buffer created in kernel mode to the user buffer we need to determine
         * where the circular buffer pointers are.
         *
         *  [    ****************               ]
         *     Start           Stop
         * 
         * If the start index is before the stop index we have a linear buffer we can copy.
         *
         */

       DbgPrint("Start Index = %i Stop Index = %i Size Of Buffer = %i\n", pExampleList->uiStartIndex, pExampleList->uiStopIndex, sizeof(pExampleList->pCircularBuffer));

       if(pExampleList->uiStartIndex < pExampleList->uiStopIndex)
       {
          UINT uiCopyLength = MIN(pExampleList->uiStopIndex - pExampleList->uiStartIndex, uiLength);

          if(uiCopyLength)
          {
              RtlCopyMemory(pData, pExampleList->pCircularBuffer + pExampleList->uiStartIndex, uiCopyLength);
              pExampleList->uiStartIndex += uiCopyLength;
              *pdwStringLength =  uiCopyLength;
              bDataRead = TRUE;
          }
       }
       else
       {

           /*
            * To copy the buffer created in kernel mode to the user buffer we need to determine
            * where the circular buffer pointers are.
            *
            *  [****               **************]
            *     Stop           Start
            * 
            * If the stop index is before the start index we have a nonlinear buffer we can copy.
            * We want to copy all the way to the end if we can.  Then we wrap around, if the
            * Start and Stop are equal, we have an empty buffer now.  If they are not then we
            * have more memory to copy.  We must always respect the buffer size provided by user mode though.
            *
            */

           if(pExampleList->uiStartIndex > pExampleList->uiStopIndex)
           {
               UINT uiLinearLengthAvailable = sizeof(pExampleList->pCircularBuffer) - pExampleList->uiStartIndex;
               UINT uiCopyLength = MIN(uiLinearLengthAvailable, uiLength);
    
    
               uiCopyLength = MIN(uiLinearLengthAvailable, uiLength);
    
               if(uiCopyLength)
               {
                   RtlCopyMemory(pData, pExampleList->pCircularBuffer + pExampleList->uiStartIndex, uiCopyLength);
    
                   pExampleList->uiStartIndex += uiCopyLength;
                   *pdwStringLength =  uiCopyLength;
                   bDataRead = TRUE;
    
                   if(pExampleList->uiStartIndex == sizeof(pExampleList->pCircularBuffer))
                   {
                      pExampleList->uiStartIndex = 0;
    
                      if(uiLength - uiCopyLength > 0)
                      {
                          UINT uiSecondCopyLength = MIN(pExampleList->uiStopIndex - pExampleList->uiStartIndex, uiLength - uiCopyLength);
    
                          if(uiSecondCopyLength)
                          {
                             RtlCopyMemory(pData, pExampleList->pCircularBuffer + pExampleList->uiStartIndex, uiCopyLength);
                             pExampleList->uiStartIndex += uiSecondCopyLength;
                             *pdwStringLength =  uiCopyLength + uiSecondCopyLength;
                             bDataRead = TRUE;
                          }
    
                      }
                   }
    
               }
           }
       }
       
       DbgPrint("Start Index = %i Stop Index = %i Size Of Buffer = %i\n", pExampleList->uiStartIndex, pExampleList->uiStopIndex, sizeof(pExampleList->pCircularBuffer));

       KeReleaseMutex(&pExampleList->kInstanceBufferMutex, FALSE);
    }

    return bDataRead;
}


/**********************************************************************
 * 
 *  Example_IsStringTerminated
 *
 *    Simple function to determine a string is NULL terminated.
 *
 **** We could validate also the characters in the string are printable! ***
 *
 **********************************************************************/
BOOLEAN Example_IsStringTerminated(PCHAR pString, UINT uiLength, UINT *pdwStringLength)
{
    BOOLEAN bStringIsTerminated = FALSE;
    UINT uiIndex = 0;
    
    DbgPrint("Example_IsStringTerminated(0x%0x, %d)\r\n", pString, uiLength);

    *pdwStringLength = 0;

    while(uiIndex < uiLength && bStringIsTerminated == FALSE)
    {
        if(pString[uiIndex] == '\0')
        {
            *pdwStringLength = uiIndex + 1; /* Include the total count we read, includes the NULL */
            bStringIsTerminated = TRUE;
            DbgPrint("  String Is Terminated!\r\n");
        }
        else
        {
           uiIndex++;
        }
    }

    return bStringIsTerminated;
}


/**********************************************************************
 * 
 *  Example_HandleSampleIoctl_DirectInIo
 *
 *    Sample IOCTL TO Handle Direct In I/O
 *
 *
 **********************************************************************/
NTSTATUS Example_HandleSampleIoctl_DirectInIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *pdwDataWritten)
{
    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
    PCHAR pInputBuffer;
    PCHAR pOutputBuffer;
    UINT dwDataRead = 0, dwDataWritten = 0;
    PCHAR pReturnData = "IOCTL - Direct In I/O From Kernel!";
    UINT dwDataSize = sizeof("IOCTL - Direct In I/O From Kernel!");
    DbgPrint("Example_HandleSampleIoctl_DirectInIo Called \r\n");

    /*
     * METHOD_IN_DIRECT
     *
     *    Input Buffer = Irp->AssociatedIrp.SystemBuffer

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -