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

📄 adddev.c

📁 这个是一个开源项目, 有能力的人可以一起来写
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * $Id: adddev.c,v 1.23 2006/11/23 11:10:10 vfrolov Exp $
 *
 * Copyright (c) 2004-2006 Vyacheslav Frolov
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 * $Log: adddev.c,v $
 * Revision 1.23  2006/11/23 11:10:10  vfrolov
 * Strict usage fixed port numbers
 *
 * Revision 1.22  2006/11/03 13:13:26  vfrolov
 * CopyStrW() now gets size in characters (not in bytes)
 *
 * Revision 1.21  2006/11/02 16:04:50  vfrolov
 * Added using fixed port numbers
 *
 * Revision 1.20  2006/10/16 08:30:45  vfrolov
 * Added the device interface registration
 *
 * Revision 1.19  2006/10/13 10:22:22  vfrolov
 * Changed name of device object (for WMI)
 *
 * Revision 1.18  2006/10/10 15:18:15  vfrolov
 * Added PortName value setting for WMI
 *
 * Revision 1.17  2006/08/23 13:48:12  vfrolov
 * Implemented WMI functionality
 *
 * Revision 1.16  2006/06/23 11:44:52  vfrolov
 * Mass replacement pDevExt by pIoPort
 *
 * Revision 1.15  2006/06/21 16:23:57  vfrolov
 * Fixed possible BSOD after one port of pair removal
 *
 * Revision 1.14  2006/03/29 09:39:28  vfrolov
 * Fixed possible usage uninitialized portName
 *
 * Revision 1.13  2006/03/27 09:38:23  vfrolov
 * Utilized StrAppendDeviceProperty()
 *
 * Revision 1.12  2006/02/26 08:35:55  vfrolov
 * Added check for start/stop queue matching
 *
 * Revision 1.11  2006/01/10 10:17:23  vfrolov
 * Implemented flow control and handshaking
 * Implemented IOCTL_SERIAL_SET_XON and IOCTL_SERIAL_SET_XOFF
 * Added setting of HoldReasons, WaitForImmediate and AmountInOutQueue
 *   fields of SERIAL_STATUS for IOCTL_SERIAL_GET_COMMSTATUS
 *
 * Revision 1.10  2005/09/27 16:41:01  vfrolov
 * Fixed DeviceType
 *
 * Revision 1.9  2005/09/06 07:23:44  vfrolov
 * Implemented overrun emulation
 *
 * Revision 1.8  2005/08/23 15:49:21  vfrolov
 * Implemented baudrate emulation
 *
 * Revision 1.7  2005/08/16 16:36:33  vfrolov
 * Hidden timeout functions
 *
 * Revision 1.6  2005/07/14 13:51:08  vfrolov
 * Replaced ASSERT by HALT_UNLESS
 *
 * Revision 1.5  2005/07/13 16:12:36  vfrolov
 * Added c0cGlobal struct for global driver's data
 *
 * Revision 1.4  2005/06/28 12:17:12  vfrolov
 * Added pBusExt to C0C_PDOPORT_EXTENSION
 *
 * Revision 1.3  2005/05/20 12:06:05  vfrolov
 * Improved port numbering
 *
 * Revision 1.2  2005/05/12 07:41:27  vfrolov
 * Added ability to change the port names
 *
 * Revision 1.1  2005/01/26 12:18:54  vfrolov
 * Initial revision
 *
 */

#include "precomp.h"
#include <initguid.h>
#include <ntddser.h>
#include "timeout.h"
#include "delay.h"
#include "strutils.h"

/*
 * FILE_ID used by HALT_UNLESS to put it on BSOD
 */
#define FILE_ID 6

NTSTATUS InitCommonExt(
    PC0C_COMMON_EXTENSION pDevExt,
    IN PDEVICE_OBJECT pDevObj,
    short doType,
    PWCHAR pPortName)
{
  pDevExt->pDevObj = pDevObj;
  pDevExt->doType = doType;
  return CopyStrW(pDevExt->portName, sizeof(pDevExt->portName)/sizeof(pDevExt->portName[0]), pPortName);
}

VOID RemoveFdoPort(IN PC0C_FDOPORT_EXTENSION pDevExt)
{
  if (pDevExt->pIoPortLocal) {
    FreeTimeouts(pDevExt->pIoPortLocal);
    FreeWriteDelay(pDevExt->pIoPortLocal);
    pDevExt->pIoPortLocal->pDevExt = NULL;
  }

  IoWMIRegistrationControl(pDevExt->pDevObj, WMIREG_ACTION_DEREGISTER);

  if (pDevExt->symbolicLinkName.Buffer) {
    IoSetDeviceInterfaceState(&pDevExt->symbolicLinkName, FALSE);
    RtlFreeUnicodeString(&pDevExt->symbolicLinkName);
  }

  if (pDevExt->ntDeviceName.Buffer) {
    RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, C0C_SERIAL_DEVICEMAP,
                           pDevExt->ntDeviceName.Buffer);
    StrFree(&pDevExt->ntDeviceName);
  }

  if (pDevExt->win32DeviceName.Buffer) {
    IoDeleteSymbolicLink(&pDevExt->win32DeviceName);
    StrFree(&pDevExt->win32DeviceName);
  }

  if (pDevExt->pLowDevObj)
    IoDetachDevice(pDevExt->pLowDevObj);

  Trace0((PC0C_COMMON_EXTENSION)pDevExt, L"RemoveFdoPort");

  IoDeleteDevice(pDevExt->pDevObj);
}

NTSTATUS AddFdoPort(IN PDRIVER_OBJECT pDrvObj, IN PDEVICE_OBJECT pPhDevObj)
{
  NTSTATUS status;
  UNICODE_STRING portName;
  PDEVICE_OBJECT pNewDevObj;
  PC0C_FDOPORT_EXTENSION pDevExt;
  PC0C_PDOPORT_EXTENSION pPhDevExt;
  ULONG emuBR, emuOverrun;
  UNICODE_STRING ntDeviceName;
  PWCHAR pPortName;

  status = STATUS_SUCCESS;
  pDevExt = NULL;
  RtlInitUnicodeString(&portName, NULL);
  RtlInitUnicodeString(&ntDeviceName, NULL);

  StrAppendDeviceProperty(&status, &ntDeviceName, pPhDevObj, DevicePropertyPhysicalDeviceObjectName);

  if (!NT_SUCCESS(status)) {
    SysLog(pPhDevObj, status, L"AddFdoPort IoGetDeviceProperty FAIL");
    goto clean;
  }

  pPhDevExt = (PC0C_PDOPORT_EXTENSION)pPhDevObj->DeviceExtension;

  if (pPhDevExt->doType != C0C_DOTYPE_PP) {
    status = STATUS_UNSUCCESSFUL;
    SysLog(pPhDevObj, status, L"AddFdoPort FAIL. Type  of PDO is not PP");
    goto clean;
  }

  Trace00((PC0C_COMMON_EXTENSION)pPhDevExt, L"AddFdoPort for ", ntDeviceName.Buffer);

  pPortName = pPhDevExt->portName;

  if (!*pPortName) {
    status = STATUS_UNSUCCESSFUL;
    SysLog(pPhDevObj, status, L"AddFdoPort FAIL. The PDO has invalid port name");
    goto clean;
  }

  {
    UNICODE_STRING portRegistryPath;

    RtlInitUnicodeString(&portRegistryPath, NULL);
    StrAppendStr(&status, &portRegistryPath, c0cGlobal.registryPath.Buffer, c0cGlobal.registryPath.Length);
    StrAppendStr0(&status, &portRegistryPath, L"\\Parameters\\");
    StrAppendStr0(&status, &portRegistryPath, pPortName);

    if (NT_SUCCESS(status)) {
      WCHAR portNameBuf[C0C_PORT_NAME_LEN + 1];
      UNICODE_STRING portNameTmp;
      RTL_QUERY_REGISTRY_TABLE queryTable[2];

      RtlZeroMemory(queryTable, sizeof(queryTable));

      portNameTmp.Length = 0;
      portNameTmp.MaximumLength = sizeof(portNameBuf);
      portNameTmp.Buffer = portNameBuf;

      queryTable[0].Flags        = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
      queryTable[0].Name         = L"PortName";
      queryTable[0].EntryContext = &portNameTmp;

      status = RtlQueryRegistryValues(
          RTL_REGISTRY_ABSOLUTE,
          portRegistryPath.Buffer,
          queryTable,
          NULL,
          NULL);

      if (!NT_SUCCESS(status) || !portNameTmp.Length) {
        status = STATUS_SUCCESS;
        StrAppendStr0(&status, &portName, pPortName);
      } else {
        StrAppendStr(&status, &portName, portNameTmp.Buffer, portNameTmp.Length);
        Trace00((PC0C_COMMON_EXTENSION)pPhDevExt, L"PortName set to ", portName.Buffer);
      }
    }

    emuBR = emuOverrun = 0;

    if (NT_SUCCESS(status)) {
      RTL_QUERY_REGISTRY_TABLE queryTable[3];
      ULONG zero = 0;

      RtlZeroMemory(queryTable, sizeof(queryTable));

      queryTable[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
      queryTable[0].Name          = L"EmuBR";
      queryTable[0].EntryContext  = &emuBR;
      queryTable[0].DefaultType   = REG_DWORD;
      queryTable[0].DefaultData   = &zero;
      queryTable[0].DefaultLength = sizeof(ULONG);

      queryTable[1].Flags         = RTL_QUERY_REGISTRY_DIRECT;
      queryTable[1].Name          = L"EmuOverrun";
      queryTable[1].EntryContext  = &emuOverrun;
      queryTable[1].DefaultType   = REG_DWORD;
      queryTable[1].DefaultData   = &zero;
      queryTable[1].DefaultLength = sizeof(ULONG);

      RtlQueryRegistryValues(
          RTL_REGISTRY_ABSOLUTE,
          portRegistryPath.Buffer,
          queryTable,
          NULL,
          NULL);
    }

    StrFree(&portRegistryPath);
  }

  if (!NT_SUCCESS(status)) {
    SysLog(pPhDevObj, status, L"AddFdoPort FAIL");
    goto clean;
  }

  {
    HANDLE hKey;

    status = IoOpenDeviceRegistryKey(pPhDevObj,
                                     PLUGPLAY_REGKEY_DEVICE,
                                     STANDARD_RIGHTS_READ,
                                     &hKey);

    if (status == STATUS_SUCCESS) {
      UNICODE_STRING keyName;

      RtlInitUnicodeString(&keyName, L"PortName");

      status = ZwSetValueKey(hKey, &keyName, 0, REG_SZ, portName.Buffer, portName.Length + sizeof(WCHAR));

      if (!NT_SUCCESS(status))
        SysLog(pPhDevObj, status, L"ZwSetValueKey(PortName) FAIL");

      ZwClose(hKey);
    } else {
      SysLog(pPhDevObj, status, L"IoOpenDeviceRegistryKey(PLUGPLAY_REGKEY_DEVICE) FAIL");
    }
  }

  status = IoCreateDevice(pDrvObj,
                          sizeof(*pDevExt),
                          NULL,
                          FILE_DEVICE_SERIAL_PORT,
                          FILE_DEVICE_SECURE_OPEN,
                          TRUE,
                          &pNewDevObj);

  if (!NT_SUCCESS(status)) {
    SysLog(pPhDevObj, status, L"AddFdoPort IoCreateDevice FAIL");
    goto clean;
  }

  HALT_UNLESS(pNewDevObj);
  pDevExt = pNewDevObj->DeviceExtension;
  RtlZeroMemory(pDevExt, sizeof(*pDevExt));
  status = InitCommonExt((PC0C_COMMON_EXTENSION)pDevExt, pNewDevObj, C0C_DOTYPE_FP, portName.Buffer);

  if (!NT_SUCCESS(status)) {
    SysLog(pPhDevObj, status, L"AddFdoPort FAIL");
    goto clean;
  }

  pDevExt->pIoPortLocal = pPhDevExt->pIoPortLocal;
  pDevExt->pIoPortLocal->pDevExt = pDevExt;

  if (emuBR) {
    if (NT_SUCCESS(AllocWriteDelay(pDevExt->pIoPortLocal)))
      Trace0((PC0C_COMMON_EXTENSION)pDevExt, L"Enabled baudrate emulation");
    else
      SysLog(pPhDevObj, status, L"AddFdoPort AllocWriteDelay FAIL");
  } else {
    Trace0((PC0C_COMMON_EXTENSION)pDevExt, L"Disabled baudrate emulation");
  }

  if (emuOverrun) {
    pDevExt->pIoPortLocal->emuOverrun = TRUE;
    Trace0((PC0C_COMMON_EXTENSION)pDevExt, L"Enabled overrun emulation");
  } else {
    pDevExt->pIoPortLocal->emuOverrun = FALSE;
    Trace0((PC0C_COMMON_EXTENSION)pDevExt, L"Disabled overrun emulation");
  }

  AllocTimeouts(pDevExt->pIoPortLocal);

  KeInitializeSpinLock(&pDevExt->controlLock);

  RtlZeroMemory(&pDevExt->pIoPortLocal->specialChars, sizeof(pDevExt->pIoPortLocal->specialChars));
  pDevExt->pIoPortLocal->specialChars.XonChar      = 0x11;
  pDevExt->pIoPortLocal->specialChars.XoffChar     = 0x13;

  RtlZeroMemory(&pDevExt->pIoPortLocal->handFlow, sizeof(pDevExt->pIoPortLocal->handFlow));
  pDevExt->pIoPortLocal->handFlow.ControlHandShake = SERIAL_DTR_CONTROL;
  pDevExt->pIoPortLocal->handFlow.FlowReplace      = SERIAL_RTS_CONTROL;

  pDevExt->lineControl.WordLength    = 7;
  pDevExt->lineControl.Parity        = EVEN_PARITY;
  pDevExt->lineControl.StopBits      = STOP_BIT_1;
  pDevExt->baudRate.BaudRate         = 1200;

  SetWriteDelay(pDevExt->pIoPortLocal);

  pDevExt->pPhDevObj = pPhDevObj;
  pDevExt->pLowDevObj = IoAttachDeviceToDeviceStack(pNewDevObj, pPhDevObj);

  if (!pDevExt->pLowDevObj) {
    status = STATUS_NO_SUCH_DEVICE;
    SysLog(pPhDevObj, status, L"AddFdoPort IoAttachDeviceToDeviceStack FAIL");
    goto clean;
  }

  pNewDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
  pNewDevObj->Flags |= DO_BUFFERED_IO;

  /* Create symbolic links to device */

  RtlInitUnicodeString(&pDevExt->ntDeviceName, NULL);
  StrAppendStr0(&status, &pDevExt->ntDeviceName, ntDeviceName.Buffer);

  RtlInitUnicodeString(&pDevExt->win32DeviceName, NULL);
  StrAppendStr0(&status, &pDevExt->win32DeviceName, C0C_PREF_WIN32_DEVICE_NAME);
  StrAppendStr0(&status, &pDevExt->win32DeviceName, portName.Buffer);

  if (NT_SUCCESS(status)) {
    status = IoCreateSymbolicLink(&pDevExt->win32DeviceName, &pDevExt->ntDeviceName);

    if (NT_SUCCESS(status)) {
      status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, C0C_SERIAL_DEVICEMAP,
                                     pDevExt->ntDeviceName.Buffer, REG_SZ,
                                     portName.Buffer,
                                     portName.Length + sizeof(WCHAR));

      if (!NT_SUCCESS(status)) {
        StrFree(&pDevExt->ntDeviceName);

        SysLog(pPhDevObj, status, L"AddFdoPort RtlWriteRegistryValue" C0C_SERIAL_DEVICEMAP L" FAIL");
      }
    } else {
      StrFree(&pDevExt->win32DeviceName);
      StrFree(&pDevExt->ntDeviceName);

      SysLog(pPhDevObj, status, L"AddFdoPort IoCreateSymbolicLink FAIL");
    }
  } else {
    StrFree(&pDevExt->win32DeviceName);
    StrFree(&pDevExt->ntDeviceName);

⌨️ 快捷键说明

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