注册表_操作

#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <NTDDK.h>
#ifdef __cplusplus
}
#endif 
#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")
#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define INITDATA data_seg("INIT")
#define arraysize(p) (sizeof(p)/sizeof((p)[0]))
typedef struct _DEVICE_EXTENSION {
	PDEVICE_OBJECT pDevice;
	UNICODE_STRING ustrDeviceName;	//设备名称
	UNICODE_STRING ustrSymLinkName;	//符号链接名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
// 函数声明
NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
								 IN PIRP pIrp);
#include "Driver.h"
#define  MY_REG_SOFTWARE_KEY_NAME		L"\\Registry\\Machine\\Software\\Zhangfan"
#pragma INITCODE
VOID CreateRegTest() //创建或打开某注册表项目
{
	UNICODE_STRING RegUnicodeString;
	HANDLE hRegister;
	RtlInitUnicodeString( &RegUnicodeString,MY_REG_SOFTWARE_KEY_NAME);//初始化UNICODE_STRING字符串
	OBJECT_ATTRIBUTES objectAttributes;
	InitializeObjectAttributes(&objectAttributes,&RegUnicodeString,OBJ_CASE_INSENSITIVE,NULL, NULL );//对大小写敏感		初始化objectAttributes
	ULONG ulResult;
	NTSTATUS ntStatus = ZwCreateKey( &hRegister,KEY_ALL_ACCESS,&objectAttributes,0,NULL,REG_OPTION_NON_VOLATILE,&ulResult);//创建或带开注册表项目
	if (NT_SUCCESS(ntStatus))//创建成功
	{
		if(ulResult==REG_CREATED_NEW_KEY)//判断是被新创建,还是已经被创建
		{
			KdPrint(("The register item is created\n"));//新创建
		}else if(ulResult==REG_OPENED_EXISTING_KEY)//已经创建了
		{
			KdPrint(("The register item has been created,and now is opened\n"));
		}
	}
	//(2)创建或打开某注册表项目的子项
	UNICODE_STRING subRegUnicodeString;
	HANDLE hSubRegister;
	RtlInitUnicodeString( &subRegUnicodeString, L"SubItem");//初始化UNICODE_STRING字符串
	OBJECT_ATTRIBUTES subObjectAttributes;
	InitializeObjectAttributes(&subObjectAttributes,&subRegUnicodeString,OBJ_CASE_INSENSITIVE, hRegister, NULL );//对大小写敏感		初始化subObjectAttributes
	ntStatus = ZwCreateKey( &hSubRegister,KEY_ALL_ACCESS,&subObjectAttributes,0,NULL,REG_OPTION_NON_VOLATILE,&ulResult);//创建或带开注册表项目
	if (NT_SUCCESS(ntStatus))
	{
		if(ulResult==REG_CREATED_NEW_KEY)//判断是被新创建,还是已经被创建
		{
			KdPrint(("The sub register item is created\n"));
		}else if(ulResult==REG_OPENED_EXISTING_KEY)
		{
			KdPrint(("The sub register item has been created,and now is opened\n"));
		}
	}
	//关闭注册表句柄
	ZwClose(hRegister);
	ZwClose(hSubRegister);
}
#pragma INITCODE
VOID OpenRegTest()
{
	UNICODE_STRING RegUnicodeString;
	HANDLE hRegister;
	//初始化UNICODE_STRING字符串
	RtlInitUnicodeString( &RegUnicodeString, MY_REG_SOFTWARE_KEY_NAME);
	OBJECT_ATTRIBUTES objectAttributes;
	//初始化objectAttributes
	InitializeObjectAttributes(&objectAttributes,&RegUnicodeString,OBJ_CASE_INSENSITIVE,NULL, NULL );//对大小写敏感
	//打开注册表
	NTSTATUS ntStatus = ZwOpenKey( &hRegister,KEY_ALL_ACCESS,&objectAttributes);
	if (NT_SUCCESS(ntStatus))
	{
		KdPrint(("Open register successfully\n"));
	}
	ZwClose(hRegister);
}
#pragma INITCODE
VOID DeleteItemRegTest()//删除子项 删除没有子项的项
{
	UNICODE_STRING RegUnicodeString;
	HANDLE hRegister;
#define MY_REG_SOFTWARE_KEY_NAME1 L"\\Registry\\Machine\\Software\\Zhangfan\\SubItem"
	RtlInitUnicodeString( &RegUnicodeString,MY_REG_SOFTWARE_KEY_NAME1);//初始化UNICODE_STRING字符串
	OBJECT_ATTRIBUTES objectAttributes;
	InitializeObjectAttributes(&objectAttributes,&RegUnicodeString,OBJ_CASE_INSENSITIVE,NULL, NULL );//对大小写敏感		初始化objectAttributes
	NTSTATUS ntStatus = ZwOpenKey( &hRegister,KEY_ALL_ACCESS,&objectAttributes);//打开注册表
	if (NT_SUCCESS(ntStatus))//打开成功 获得句柄
	{
		KdPrint(("Open register successfully\n"));
	}
	ntStatus = ZwDeleteKey(hRegister);//删除 SubItem
	if (NT_SUCCESS(ntStatus))
	{
		KdPrint(("Delete the item successfully\n"));
	}else if(ntStatus == STATUS_ACCESS_DENIED)
	{
		KdPrint(("STATUS_ACCESS_DENIED\n"));

	}else if(ntStatus == STATUS_INVALID_HANDLE)
	{
		KdPrint(("STATUS_INVALID_HANDLE\n"));
	}else
	{
		KdPrint(("Maybe the item has sub item to delete\n"));
	}
	ZwClose(hRegister);
}
#pragma INITCODE
VOID SetRegTest()//设置键值
{
	UNICODE_STRING RegUnicodeString;
	HANDLE hRegister;
	RtlInitUnicodeString( &RegUnicodeString, MY_REG_SOFTWARE_KEY_NAME);//初始化UNICODE_STRING字符串
	OBJECT_ATTRIBUTES objectAttributes;
	InitializeObjectAttributes(&objectAttributes,&RegUnicodeString,OBJ_CASE_INSENSITIVE,NULL, NULL );//对大小写敏感		初始化objectAttributes
	NTSTATUS ntStatus = ZwOpenKey( &hRegister,KEY_ALL_ACCESS,&objectAttributes);//打开注册表 L"\\Registry\\Machine\\Software\\Zhangfan"
	if (NT_SUCCESS(ntStatus))
	{
		KdPrint(("Open register successfully\n"));
	}
	UNICODE_STRING ValueName;
	RtlInitUnicodeString( &ValueName, L"REG_DWORD 李赛赛");//初始化ValueName
	ULONG ulValue = 1000;
	ZwSetValueKey(hRegister,&ValueName,0,REG_DWORD,&ulValue,sizeof(ulValue));//设置REG_DWORD子键	李赛赛	1000
	RtlInitUnicodeString(&ValueName, L"REG_SZ 李发起");//初始化ValueName
	WCHAR* strValue = L"hello world";
	ZwSetValueKey(hRegister,&ValueName,0,REG_SZ,strValue,wcslen(strValue)*2+2);//设置REG_SZ子键		李发起	"hello world"
	RtlInitUnicodeString( &ValueName, L"REG_BINARY 邱坤");//初始化ValueName
	UCHAR buffer[10];
	RtlFillMemory(buffer,sizeof(buffer),0xFF);
	ZwSetValueKey(hRegister,&ValueName,0,REG_BINARY,buffer,sizeof(buffer));//设置REG_MULTI_SZ子键	邱坤	二进制0xff
	ZwClose(hRegister);//关闭注册表句柄
}
#pragma INITCODE
VOID QueryRegTest()//查询注册表键值
{
	UNICODE_STRING RegUnicodeString;
	HANDLE hRegister;
	RtlInitUnicodeString( &RegUnicodeString,MY_REG_SOFTWARE_KEY_NAME);//初始化UNICODE_STRING字符串
	OBJECT_ATTRIBUTES objectAttributes;
	InitializeObjectAttributes(&objectAttributes,&RegUnicodeString,OBJ_CASE_INSENSITIVE,NULL, NULL );//对大小写敏感		初始化objectAttributes
	NTSTATUS ntStatus = ZwOpenKey( &hRegister,KEY_ALL_ACCESS,&objectAttributes);//打开注册表
	if (NT_SUCCESS(ntStatus))
	{
		KdPrint(("Open register successfully\n"));
	}
	UNICODE_STRING ValueName;
	RtlInitUnicodeString( &ValueName, L"REG_DWORD 李赛赛");//初始化ValueName
	ULONG ulSize;//读取REG_DWORD子键
	ntStatus = ZwQueryValueKey(hRegister,&ValueName,KeyValuePartialInformation ,NULL,0,&ulSize);//查询注册表键值 三种   获取这种数据结构体的长度
	if (ntStatus==STATUS_OBJECT_NAME_NOT_FOUND || ulSize==0)
	{
		ZwClose(hRegister);
		KdPrint(("The item is not exist\n"));
		return;
	}
	PKEY_VALUE_PARTIAL_INFORMATION pvpi = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(PagedPool,ulSize);
	ntStatus = ZwQueryValueKey(hRegister,&ValueName,KeyValuePartialInformation ,pvpi,ulSize,&ulSize);//查询注册表键值 三种
	if (!NT_SUCCESS(ntStatus))
	{
		ZwClose(hRegister);
		KdPrint(("Read regsiter error\n"));
		return;
	}
	//判断是否为REG_DWORD类型
	if (pvpi->Type==REG_DWORD && pvpi->DataLength==sizeof(ULONG))
	{
		PULONG pulValue = (PULONG) pvpi->Data;
		KdPrint(("打印数值The value:%d\n",*pulValue));//查询到的数据的值
	}
	ExFreePool(pvpi);
	RtlInitUnicodeString( &ValueName, L"REG_SZ 李发起");//初始化ValueName
	
	ntStatus = ZwQueryValueKey(hRegister,&ValueName,KeyValuePartialInformation ,NULL,0,&ulSize);//读取REG_SZ子键  小的结构体体 先自己查询大小 再申请结构体
	if (ntStatus==STATUS_OBJECT_NAME_NOT_FOUND || ulSize==0)
	{
		ZwClose(hRegister);
		KdPrint(("The item is not exist\n"));
		return;
	}
	pvpi = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(PagedPool,ulSize);
	ntStatus = ZwQueryValueKey(hRegister,&ValueName,KeyValuePartialInformation ,pvpi,ulSize,&ulSize);//查询键值
	if (!NT_SUCCESS(ntStatus))
	{
		ZwClose(hRegister);
		KdPrint(("Read regsiter error\n"));
		return;
	}
	//判断是否为REG_SZ类型
	if (pvpi->Type==REG_SZ)
	{
		KdPrint(("打印字符串The value:%S\n",pvpi->Data));//打印字符串
	}
	ZwClose(hRegister);
}
#pragma INITCODE
VOID EnumerateSubItemRegTest()
{
	UNICODE_STRING RegUnicodeString;
	HANDLE hRegister;
	RtlInitUnicodeString( &RegUnicodeString, MY_REG_SOFTWARE_KEY_NAME);//初始化UNICODE_STRING字符串
	OBJECT_ATTRIBUTES objectAttributes;
	InitializeObjectAttributes(&objectAttributes,&RegUnicodeString,OBJ_CASE_INSENSITIVE,NULL, NULL );//对大小写敏感		初始化objectAttributes
	NTSTATUS ntStatus = ZwOpenKey( &hRegister,KEY_ALL_ACCESS,&objectAttributes);//打开注册表
	if (NT_SUCCESS(ntStatus))
	{
		KdPrint(("打开注册表成功 Open register successfully\n"));
	}
	ULONG ulSize;
	ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize);//第一次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的长度
	PKEY_FULL_INFORMATION pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool,ulSize);
	ZwQueryKey(hRegister,KeyFullInformation,pfi,ulSize,&ulSize);//第二次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的数据
	for (ULONG i=0;i<pfi->SubKeys;i++)//项的个数
	{
		ZwEnumerateKey(hRegister,i,KeyBasicInformation,NULL,0,&ulSize);//第一次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的长度   结构体的长度
		PKEY_BASIC_INFORMATION pbi =(PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool,ulSize);
		ZwEnumerateKey(hRegister,i,KeyBasicInformation,pbi,ulSize,&ulSize);//第二次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的数据
		UNICODE_STRING uniKeyName;
		uniKeyName.Length = uniKeyName.MaximumLength =(USHORT)pbi->NameLength;
		uniKeyName.Buffer = pbi->Name;//名字
		KdPrint(("子项:The %d sub item name:%wZ\n",i,&uniKeyName));
		ExFreePool(pbi);
	}
	ExFreePool(pfi);
	ZwClose(hRegister);
}
#pragma INITCODE
VOID EnumerateSubValueRegTest()
{
	UNICODE_STRING RegUnicodeString;
	HANDLE hRegister;
	RtlInitUnicodeString( &RegUnicodeString,MY_REG_SOFTWARE_KEY_NAME);//初始化UNICODE_STRING字符串
	OBJECT_ATTRIBUTES objectAttributes;
	InitializeObjectAttributes(&objectAttributes,&RegUnicodeString,OBJ_CASE_INSENSITIVE,NULL, NULL );//对大小写敏感		//初始化objectAttributes
	NTSTATUS ntStatus = ZwOpenKey( &hRegister,KEY_ALL_ACCESS,&objectAttributes);//打开注册表
	if (NT_SUCCESS(ntStatus))
	{
		KdPrint(("Open register successfully\n"));
	}
	ULONG ulSize;
	ZwQueryKey(hRegister,KeyFullInformation,NULL,0,&ulSize);//得到项的结构体的大小 要申请内存
	PKEY_FULL_INFORMATION pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool,ulSize);
	ZwQueryKey(hRegister,KeyFullInformation,pfi,ulSize,&ulSize);//得到项的个数
	for (ULONG i=0;i<pfi->Values;i++)//项的个数
	{
		ZwEnumerateValueKey(hRegister,i,KeyValueBasicInformation,NULL,0,&ulSize);//得到结构体的大小 要申请内存
		PKEY_VALUE_BASIC_INFORMATION pvbi =(PKEY_VALUE_BASIC_INFORMATION)ExAllocatePool(PagedPool,ulSize);
		ZwEnumerateValueKey(hRegister,i,KeyValueBasicInformation,pvbi,ulSize,&ulSize);
		UNICODE_STRING uniKeyName;
		uniKeyName.Length = uniKeyName.MaximumLength =(USHORT)pvbi->NameLength;
		uniKeyName.Buffer = pvbi->Name;//键的名字
		KdPrint(("The %d sub value name:%wZ\n",i,&uniKeyName));
		if (pvbi->Type==REG_SZ)
		{
			KdPrint(("The sub value type:REG_SZ\n"));
		}else if (pvbi->Type==REG_MULTI_SZ)
		{
			KdPrint(("The sub value type:REG_MULTI_SZ\n")); 

		}else if (pvbi->Type==REG_DWORD)
		{
			KdPrint(("The sub value type:REG_DWORD\n")); 
		}else if (pvbi->Type==REG_BINARY)
		{
			KdPrint(("The sub value type:REG_BINARY\n")); 
		}

		ExFreePool(pvbi);
	}
	ExFreePool(pfi);
	ZwClose(hRegister);
}
#pragma INITCODE
void RtlRegTest()//rtl简单函数 封装
{
	//创建子项目
	NTSTATUS ntStatus =RtlCreateRegistryKey(RTL_REGISTRY_SERVICES,L"HelloDDK\\Zhangfan");//Registry\Machine\System\CurrentControlSet\Services
	if (NT_SUCCESS(ntStatus))
	{	KdPrint(("Create the item successfully\n"));
	}
	ntStatus =RtlCheckRegistryKey(RTL_REGISTRY_SERVICES,L"HelloDDK\\Zhangfan");//检查某项是否存在
	if (NT_SUCCESS(ntStatus))
	{	KdPrint(("The item is exist\n"));
	}
	ULONG value1 = 100;
	ntStatus = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, L"HelloDDK\\Zhangfan", L"DWORD_Value_李赛赛", REG_DWORD, &value1, sizeof(value1));	//写入REG_DWORD的数据
	if (NT_SUCCESS(ntStatus))
	{	KdPrint(("Write the DWORD value succuessfully\n"));
	}
	PWCHAR szString = L"Hello DDK";
	ntStatus = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,L"HelloDDK\\Zhangfan",L"SZ_Value_邱坤",REG_SZ,szString,wcslen(szString)*2+2);
	if (NT_SUCCESS(ntStatus))
	{KdPrint(("Write the REG_SZ value succuessfully\n"));
	}
    RTL_QUERY_REGISTRY_TABLE paramTable[2];
    RtlZeroMemory(paramTable, sizeof(paramTable));
	ULONG defaultData=0;
	ULONG uQueryValue;
    paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
    paramTable[0].Name = L"DWORD_Value";
    paramTable[0].EntryContext = &uQueryValue;
    paramTable[0].DefaultType = REG_DWORD;
    paramTable[0].DefaultData = &defaultData;
    paramTable[0].DefaultLength = sizeof(ULONG);
	ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,L"HelloDDK\\Zhangfan",paramTable,NULL,NULL);//查询REG_DWORD的数据
	if (NT_SUCCESS(ntStatus))
	{
		KdPrint(("Query the item successfully\n"));
		KdPrint(("The item is :%d\n",uQueryValue));//查询到的值
	}
	ntStatus = RtlDeleteRegistryValue(RTL_REGISTRY_SERVICES,L"HelloDDK\\Zhangfan",L"DWORD_Value_李赛赛");//删除子键
	if (NT_SUCCESS(ntStatus))
	{
		KdPrint(("delete the value successfully\n"));
	}
	KdPrint(("执行完毕"));
}
#pragma INITCODE
VOID RegTest() 
{
 	//CreateRegTest();
// 	OpenRegTest();
	//SetRegTest();
	//QueryRegTest();
//EnumerateSubItemRegTest();
	//EnumerateSubValueRegTest();
	//DeleteItemRegTest();
//RtlRegTest();
}

/************************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
      pDriverObject:从I/O管理器中传进来的驱动对象
      pRegistryPath:驱动程序在注册表的中的路径
* 返回 值:返回初始化驱动状态
*************************************************************************/
#pragma INITCODE
extern "C" NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath	) 
{
	NTSTATUS status;
	KdPrint(("Enter DriverEntry\n"));
	//注册其他驱动调用函数入口
	pDriverObject->DriverUnload = HelloDDKUnload;
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
	//创建驱动设备对象
	status = CreateDevice(pDriverObject);
	RegTest();
	KdPrint(("DriverEntry end\n"));
	return status;
}
/************************************************************************
* 函数名称:CreateDevice
* 功能描述:初始化设备对象
* 参数列表:
      pDriverObject:从I/O管理器中传进来的驱动对象
* 返回 值:返回初始化状态
*************************************************************************/
#pragma INITCODE
NTSTATUS CreateDevice (IN PDRIVER_OBJECT	pDriverObject) 
{
	NTSTATUS status;
	PDEVICE_OBJECT pDevObj;
	PDEVICE_EXTENSION pDevExt;	//创建设备名称
	UNICODE_STRING devName;
	RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
	//创建设备
	status = IoCreateDevice( pDriverObject,sizeof(DEVICE_EXTENSION),&(UNICODE_STRING)devName,FILE_DEVICE_UNKNOWN,0, TRUE,&pDevObj );
	if (!NT_SUCCESS(status))
		return status;
	pDevObj->Flags |= DO_BUFFERED_IO;
	pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
	pDevExt->pDevice = pDevObj;
	pDevExt->ustrDeviceName = devName;
	//创建符号链接
	UNICODE_STRING symLinkName;
	RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
	pDevExt->ustrSymLinkName = symLinkName;
	status = IoCreateSymbolicLink( &symLinkName,&devName );
	if (!NT_SUCCESS(status)) 
	{
		IoDeleteDevice( pDevObj );
		return status;
	}
	return STATUS_SUCCESS;
}

/************************************************************************
* 函数名称:HelloDDKUnload
* 功能描述:负责驱动程序的卸载操作
* 参数列表:
      pDriverObject:驱动对象
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject) 
{
	PDEVICE_OBJECT	pNextObj;
	KdPrint(("Enter DriverUnload\n"));
	pNextObj = pDriverObject->DeviceObject;
	//while (pNextObj != NULL) 
	//{
	//	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
	//		pNextObj->DeviceExtension;

	//	//删除符号链接
	//	UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
	//	IoDeleteSymbolicLink(&pLinkName);
	//	pNextObj = pNextObj->NextDevice;
	//	IoDeleteDevice( pDevExt->pDevice );
	//}
	UNICODE_STRING symLinkName;
	RtlInitUnicodeString(&symLinkName, L"\\??\\HelloDDK");
	IoDeleteSymbolicLink(&symLinkName);//删除符号连接    
	IoDeleteDevice(pDriverObject->DeviceObject);//删除设备    
}
/************************************************************************
* 函数名称:HelloDDKDispatchRoutine
* 功能描述:对读IRP进行处理
* 参数列表:
      pDevObj:功能设备对象
      pIrp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp) 
{
	KdPrint(("Enter HelloDDKDispatchRoutine\n"));
	NTSTATUS status = STATUS_SUCCESS;
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = 0;	// bytes xfered
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );// 完成IRP
	KdPrint(("Leave HelloDDKDispatchRoutine\n"));
	return status;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值