忆杰的博客

忆杰的博客

内核中注册表操作

内核中的注册表操作和Win32下面是没有什么区别的. 最多来说就是函数的名字稍微换了下. 都是一个套路. 所以说学习新东西啊, 都是建立在旧东西的基础之上.而且内核中好像有一些比Win32更加好用的注册表操作函数. 一句话就可以实现很多功能. 真是舒服. 这些东西的话, 其实没有什么好说的,直接上代码吧, 代码能够说明一切.

 
内核中对注册表也就是那么个操作套路, 增删改查.遍历撒的. 好像很多都是只是换了个名称, 而且本来他们本来就是一个套路, Win32函数调用的时候进入内核也是调用那么些函数. 所以这些东西不需要多说了!!

/*
	Windows内核下注册表的操作!
	编译方法参见makefile. TAB = 8
	HKEY_LOCAL_MACHINE	= \Registry\Machine
	HKEY_USERS		= \Registry\User
	HKEY_CURRENT_CONFIG	= \Registry\Machine\SYSTEM\CurrentControlSet\Hardware\Profiles\Current
	HKEY_CLASSES_ROOT	= \Registry\Machine\SOFTWARE\Classes\
*/
#include <ntddk.h>
#include <ntstrsafe.h>
#define  REG_SOFTWARE_KEY_NAME		L"\\Registry\\Machine\\Software\\JoenRegister"
#define  REG_SOFTWARE_VALUE_NAME	L"SubItem"
//===========================================================================
//创建新键值
#pragma  code_seg( "INIT" )
NTSTATUS CreateNewKey( ) {
	HANDLE		hKey;
	HANDLE		hKey2;
	ULONG		ulResult;
	OBJECT_ATTRIBUTES Obj_Attr;
	NTSTATUS Status;
	UNICODE_STRING UStKeyName = RTL_CONSTANT_STRING( REG_SOFTWARE_KEY_NAME );
	UNICODE_STRING UStValueName = RTL_CONSTANT_STRING( REG_SOFTWARE_VALUE_NAME );
	
	
	InitializeObjectAttributes(&Obj_Attr, &UStKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
	
	//创建或带开注册表项目
	Status = ZwCreateKey( &hKey,KEY_ALL_ACCESS,&Obj_Attr,0,NULL,REG_OPTION_NON_VOLATILE,&ulResult );
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "创建/打开\\Registry\\Machine\\Software\\JoenRegister注册表失败!\n" ));
		return Status;
	}else {
		//判断是被新创建,还是已经被创建
		if( ulResult == REG_CREATED_NEW_KEY ) {
			KdPrint(("创建\\Registry\\Machine\\Software\\JoenRegister键值成功\n"));
		}else if( ulResult == REG_OPENED_EXISTING_KEY )	{
			KdPrint(("打开\\Registry\\Machine\\Software\\JoenRegister键值成功\n"));
		}
	}
	
	//打开一个注册表句柄下的一个子项目
	InitializeObjectAttributes( &Obj_Attr, &UStValueName, OBJ_CASE_INSENSITIVE, hKey, NULL );
	
	//创建/打开一个注册表句柄下的另一个句柄
	Status = ZwCreateKey( &hKey2,KEY_ALL_ACCESS,&Obj_Attr,0,NULL,REG_OPTION_NON_VOLATILE,&ulResult);
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "创建/打开子句柄SubItem失败!\n" ));
		return Status;
	}else {
		//判断是被新创建,还是已经被创建
		if( ulResult == REG_CREATED_NEW_KEY ) {
			KdPrint(("创建子句柄SubItem成功\n"));
		}else if( ulResult == REG_OPENED_EXISTING_KEY )	{
			KdPrint(("打开子句柄SubItem成功\n"));
		}
	}
	
	ZwClose( hKey2 );
	ZwClose( hKey );
//----------------------------------------------------------------------------	
	InitializeObjectAttributes( &Obj_Attr, &UStKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );

	//只是打开注册表项目, 如果不存在返回失败
	Status = ZwOpenKey( &hKey,KEY_ALL_ACCESS, &Obj_Attr );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "打开\\Registry\\Machine\\Software\\JoenRegister失败\n" ));
			return Status;
		}else {
			KdPrint(( "打开\\Registry\\Machine\\Software\\JoenRegister成功\n" ));
	}
	ZwClose( hKey );
	return Status;
}
//===========================================================================
//设置键值试验, 设置键值可以覆盖原来的值.
#pragma  code_seg( "INIT" )
NTSTATUS SetKeyValue() {
	HANDLE		hKey = 0;
	ULONG		ulResult;
	ULONG		ulValue;
	NTSTATUS	Status;
	CHAR byArr[8]	= {0};
	OBJECT_ATTRIBUTES Obj_Attr;
	UNICODE_STRING UStValueKey = RTL_CONSTANT_STRING( L"Reg_Sz" );
	UNICODE_STRING UStKeyName = RTL_CONSTANT_STRING( REG_SOFTWARE_KEY_NAME );
	InitializeObjectAttributes(&Obj_Attr, &UStKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );

	//创建或带开注册表项目
	Status = ZwCreateKey( &hKey,KEY_ALL_ACCESS,&Obj_Attr,0,NULL,REG_OPTION_NON_VOLATILE,&ulResult );
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "创建/打开\\Registry\\Machine\\Software\\JoenRegister注册表失败!\n" ));
		return Status;
	}else {
		//判断是被新创建,还是已经被创建
		if( ulResult == REG_CREATED_NEW_KEY ) {
			KdPrint(("创建\\Registry\\Machine\\Software\\JoenRegister键值成功\n"));
		}else if( ulResult == REG_OPENED_EXISTING_KEY )	{
			KdPrint(("打开\\Registry\\Machine\\Software\\JoenRegister键值成功\n"));
		}
	}

	do {
		//设置默认键值
		Status = ZwSetValueKey(hKey, (PUNICODE_STRING)byArr, 0,REG_SZ, L"Hello",sizeof(L"hello")+2);
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "设置默认键值失败\n" ));
			break;
		}

		//设置某个键的键值
		Status = ZwSetValueKey(hKey, &UStValueKey, 0, REG_SZ, L"String", sizeof(L"String")+2 );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "设置Reg_Sz键值失败\n" ));
			break;
		}
		
		//设置某个键的键值 DWORD类型
		ulValue = 100;
		RtlInitUnicodeString(&UStValueKey, L"Reg_Dword" );
		Status = ZwSetValueKey(hKey, &UStValueKey, 0, REG_DWORD, &ulValue, sizeof(ulValue));
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "设置Reg_Sz键值失败\n" ));
			break;
		}
	} while ( FALSE );
	
	if ( hKey ) {
		ZwClose(hKey);
	}
	return Status;
}
//===========================================================================
//查询键值试验, 这个查询键值ZwQueryValueKey 和那个ZwQuery, 注意区分
#pragma  code_seg( "INIT" )
NTSTATUS QueryValueInfo() {
	HANDLE		hKey = 0;
	ULONG		ulResult;
	ULONG		ulSize;
	NTSTATUS	Status;
	OBJECT_ATTRIBUTES Obj_Attr;
	UNICODE_STRING UStValueKey = RTL_CONSTANT_STRING( L"Reg_Dword" );
	UNICODE_STRING UStKeyName = RTL_CONSTANT_STRING( REG_SOFTWARE_KEY_NAME );
	PKEY_VALUE_PARTIAL_INFORMATION pKeyPartialInfo = NULL;

	InitializeObjectAttributes(&Obj_Attr, &UStKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL );
	
	//创建或带开注册表项目
	Status = ZwCreateKey( &hKey,KEY_ALL_ACCESS,&Obj_Attr,0,NULL,REG_OPTION_NON_VOLATILE,&ulResult );
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "创建/打开\\Registry\\Machine\\Software\\JoenRegister注册表失败!\n" ));
		return Status;
	}else {
		//判断是被新创建,还是已经被创建
		if( ulResult == REG_CREATED_NEW_KEY ) {
			KdPrint(("创建\\Registry\\Machine\\Software\\JoenRegister键值成功\n"));
		}else if( ulResult == REG_OPENED_EXISTING_KEY )	{
			KdPrint(("打开\\Registry\\Machine\\Software\\JoenRegister键值成功\n"));
		}
	}
	
	do {
		//读取REG_DWORD子键, 这里只是尝试着搞一下
		Status = ZwQueryValueKey( hKey, &UStValueKey, KeyValuePartialInformation,NULL,0,&ulSize);
		if ( Status == STATUS_OBJECT_NAME_NOT_FOUND || ulSize==0 ) {
			KdPrint(("Reg_Dword子键不存在\n"));
			break;
		}
		
		//分配结构需要的内存
		pKeyPartialInfo = ExAllocatePool(PagedPool,ulSize);
		if ( !pKeyPartialInfo ) {
			KdPrint(( "pKeyPartialInfo内存分配失败\n" ));
			break;
		}
		
		//这次才是真正的查询
		Status = ZwQueryValueKey(hKey, &UStValueKey,KeyValuePartialInformation,
				pKeyPartialInfo,ulSize,&ulSize);
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(("读取Reg_Dword子键失败\n"));
			break;
		}

		//判断是否为REG_DWORD类型
		if (pKeyPartialInfo->Type==REG_DWORD && pKeyPartialInfo->DataLength==sizeof(ULONG))
		{
			KdPrint(("查询子键 Reg_Dword:%d\n", *((PULONG)pKeyPartialInfo->Data)) );
		}
		
		if ( pKeyPartialInfo ) {
			ExFreePool( pKeyPartialInfo );
			pKeyPartialInfo = NULL;
		}
//---------------------------------------------------------------------------
		RtlInitUnicodeString( &UStValueKey, L"Reg_Sz" );
		//读取REG_SZ子键
		Status = ZwQueryValueKey(hKey,&UStValueKey,KeyValuePartialInformation,NULL,0,&ulSize);
		if ( Status == STATUS_OBJECT_NAME_NOT_FOUND || ulSize==0 ) {
			KdPrint(("Reg_Sz子键不存在!\n"));
			break;
		}
		
		//分配结构需要的内存
		pKeyPartialInfo = ExAllocatePool(PagedPool,ulSize);
		if ( !pKeyPartialInfo ) {
			KdPrint(( "pKeyPartialInfo内存分配失败\n" ));
			break;
		}
		
		//这次才是真正的查询
		Status = ZwQueryValueKey(hKey, &UStValueKey,KeyValuePartialInformation,
			pKeyPartialInfo,ulSize,&ulSize);
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(("读取Reg_Sz子键失败\n"));
			break;
		}

		//判断是否为REG_SZ类型
		if (pKeyPartialInfo->Type==REG_SZ ){
			KdPrint(("Reg_Sz值为:%ws\n",pKeyPartialInfo->Data) );
		}
	} while ( FALSE );
//---------------------------------------------------------------------------
	if ( hKey ) {
		ZwClose(hKey);
	}
	if ( pKeyPartialInfo ) {
		ExFreePool( pKeyPartialInfo );
	}
	return Status;
}
//===========================================================================
//枚举子项中的键值, 键值哈. 
//pUSzRegPath	:要枚举的子项目名称
#pragma  code_seg( "INIT" )
VOID EnumerateSubValue( const PUNICODE_STRING pUSzRegPath ) {
	HANDLE		hKey = 0;
	ULONG		ulSize;
	ULONG		i;
	NTSTATUS	Status;
	UNICODE_STRING	UStKeyName;
	OBJECT_ATTRIBUTES Obj_Attr;
	PKEY_FULL_INFORMATION pKeyFullInfo = NULL;
	PKEY_VALUE_BASIC_INFORMATION pKeyValueBasicInfo = NULL;

	//初始化objectAttributes
	InitializeObjectAttributes( &Obj_Attr, pUSzRegPath,OBJ_CASE_INSENSITIVE,NULL,NULL);

	//打开注册表
	Status = ZwOpenKey( &hKey, KEY_ALL_ACCESS,&Obj_Attr );
	if (!NT_SUCCESS(Status)){
		return;
	}
	
	//首次尝试查询子项信息
	ZwQueryKey( hKey,KeyFullInformation,NULL,0, &ulSize );
	
	pKeyFullInfo = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool,ulSize);
	if ( !pKeyFullInfo ) {
		return;
	}

	//再次查询子项信息
	Status = ZwQueryKey( hKey, KeyFullInformation, pKeyFullInfo, ulSize, &ulSize );
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "查询子项信息失败!\n" ));
	}

	for ( i=0; i< pKeyFullInfo->Values; i++ ) {

		//枚举键值信息
		ZwEnumerateValueKey( hKey,i, KeyValueBasicInformation, NULL, 0, &ulSize );
		
		pKeyValueBasicInfo =(PKEY_VALUE_BASIC_INFORMATION)ExAllocatePool(PagedPool,ulSize);
		if ( !pKeyValueBasicInfo ) {
			KdPrint(( "内存申请失败!\n" ));
			break;
		}

		Status = ZwEnumerateValueKey(hKey,i,KeyValueBasicInformation,pKeyValueBasicInfo,
			ulSize,&ulSize);
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "枚举键值失败!\n" ));
		}
		
		UStKeyName.Length = UStKeyName.MaximumLength =(USHORT)pKeyValueBasicInfo->NameLength;
		UStKeyName.Buffer = pKeyValueBasicInfo->Name;
		
		KdPrint(("\t子项%d名称:%wZ\t",i,&UStKeyName));
		
		if (pKeyValueBasicInfo->Type==REG_SZ ){
			KdPrint(( "REG_SZ\n" ));

		}else if (pKeyValueBasicInfo->Type==REG_MULTI_SZ ){
			KdPrint(( "REG_MULTI_SZ\n" )); 

		}else if (pKeyValueBasicInfo->Type==REG_DWORD ){
			KdPrint(( "REG_DWORD\n" )); 

		}else if (pKeyValueBasicInfo->Type==REG_BINARY ){
			KdPrint(( "REG_BINARY\n" )); 
		}
		
		if ( pKeyValueBasicInfo ) {
			ExFreePool(pKeyValueBasicInfo);
			pKeyValueBasicInfo = NULL;
		}
	}
//---------------------------------------------------------------------------
	if ( pKeyFullInfo ) {
		ExFreePool(pKeyFullInfo);
	}
	if ( hKey ) {
		ZwClose(hKey);
	}
}
//===========================================================================
//枚举键值和子项测试, 删除只能从最底层开始删除.
#pragma  code_seg( "INIT" )
NTSTATUS EnumerateKeyValue() {
	HANDLE		hKey = 0;
	ULONG		ulSize;
	ULONG		i;
	NTSTATUS	Status;
	UNICODE_STRING UStKeyName;
	UNICODE_STRING UStSubKeyName;
	OBJECT_ATTRIBUTES Obj_Attr;
	PKEY_FULL_INFORMATION pKeyFullInfo = NULL;
	PKEY_BASIC_INFORMATION pKeyBasicInfo = NULL;
	UNICODE_STRING UStItemName = RTL_CONSTANT_STRING( L"\\Registry\\Machine\\Software\\" );
	

	//初始化objectAttributes
	InitializeObjectAttributes(&Obj_Attr,&UStItemName,OBJ_CASE_INSENSITIVE,NULL,NULL );

	//打开注册表
	Status = ZwOpenKey( &hKey,KEY_ALL_ACCESS,&Obj_Attr);
	if ( NT_SUCCESS( Status )) {
		KdPrint(( "打开注册表\\Registry\\Machine\\Software\\成功, 准备枚举\n" ));
	}else {
		KdPrint(( "打开注册表成功失败\n" ));
	}
	
	do {
		//第一次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的长度
		Status = ZwQueryKey(hKey,KeyFullInformation,NULL,0,&ulSize );
		
		pKeyFullInfo = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool,ulSize);
		if ( !pKeyFullInfo ) {
			KdPrint(( "内存分配失败\n" ));
			break;
		}

		//第二次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的数据
		Status = ZwQueryKey(hKey,KeyFullInformation,pKeyFullInfo,ulSize,&ulSize);
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "二次查询子键信息失败\n" ));
			break;
		}
//---------------------------------------------------------------------------
		for (i=0; i < pKeyFullInfo->SubKeys; i++ )	{

			//第一次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的长度
			ZwEnumerateKey(hKey,i,KeyBasicInformation,NULL,0,&ulSize);
			
			pKeyBasicInfo = ExAllocatePool(PagedPool,ulSize);
			if ( !pKeyBasicInfo ) {
				break;
			}

			//第二次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的数据
			Status = ZwEnumerateKey( hKey,i,KeyBasicInformation,pKeyBasicInfo,ulSize,&ulSize);
			if ( !NT_SUCCESS(Status) ) {
				KdPrint(( "枚举子键的时候遇到错误\n" ));
				break;
			}

			//填写名称信息
			UStKeyName.Length = UStKeyName.MaximumLength = (USHORT)pKeyBasicInfo->NameLength;
			UStKeyName.Buffer = pKeyBasicInfo->Name;
			
			KdPrint(("第 %d 项的名称是: %wZ\n",i,&UStKeyName));
			
			//给子字符串分配内存
			UStSubKeyName.Buffer = (PWSTR)ExAllocatePool( PagedPool, \
			sizeof(L"\\Registry\\Machine\\Software\\") + wcslen(UStKeyName.Buffer)*2+2 );

			UStSubKeyName.MaximumLength = sizeof(L"\\Registry\\Machine\\Software\\") 
					+ wcslen(UStKeyName.Buffer)*2+2;

			RtlCopyUnicodeString( &UStSubKeyName, &UStItemName );
			RtlUnicodeStringCat( &UStSubKeyName, &UStKeyName);

			//枚举子键值.
			EnumerateSubValue( &UStSubKeyName );

			if ( pKeyBasicInfo ) {
				ExFreePool( pKeyBasicInfo );
				pKeyBasicInfo = NULL;
			}
			RtlFreeUnicodeString( &UStSubKeyName );
		}

		if ( pKeyBasicInfo ) {
			ExFreePool(pKeyBasicInfo);
		}
	 } while ( FALSE );
//---------------------------------------------------------------------------
	if ( pKeyFullInfo ) {
		ExFreePool(pKeyFullInfo);
	}
	if ( hKey ) {
		ZwClose(hKey);
	}
	return Status;
}
//===========================================================================
//删除子项试验
#pragma  code_seg( "INIT" )
NTSTATUS DeleteKey() {
	HANDLE hKey = 0;
	NTSTATUS Status;
	OBJECT_ATTRIBUTES ObjAttr;
	UNICODE_STRING UStKeyName = 
		RTL_CONSTANT_STRING( L"\\Registry\\Machine\\Software\\JoenRegister\\SubItem");

	
	//初始化objectAttributes
	InitializeObjectAttributes(&ObjAttr,&UStKeyName,OBJ_CASE_INSENSITIVE,NULL,NULL );

	//打开注册表
	Status = ZwOpenKey( &hKey, KEY_ALL_ACCESS,&ObjAttr );
	if ( !NT_SUCCESS(Status) ){
		KdPrint(( "打开注册表失败!\n" ));
		return Status;
	}
	
	//删除键
	Status = ZwDeleteKey( hKey );

	if ( NT_SUCCESS(Status) ){
		KdPrint(("删除\\Registry\\Machine\\Software\\JoenRegister\\SubItem成功!\n"));

	}else if( Status == STATUS_ACCESS_DENIED ){
		KdPrint(("权限不够\n"));
		
	}else if( Status == STATUS_INVALID_HANDLE ){
		KdPrint(("句柄无效\n"));
	}else{
		KdPrint(("无法删除\n"));
	}
	
	if ( hKey ) {
		ZwClose( hKey);
	}
	return Status;
}
//===========================================================================
//Rtl系列函数试验
#pragma  code_seg( "INIT" )
NTSTATUS RtlRegister() {
	ULONG		ulValue;
	NTSTATUS	Status;
	ULONG		ulDefaultData=0;
	ULONG		ulQueryValue;
	PWCHAR		SzString = L"Sz_Hello";
	RTL_QUERY_REGISTRY_TABLE RtlQueryTab[2] = {0};

	//按照绝对路径创建一个键
	Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,REG_SOFTWARE_KEY_NAME );
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "创建子键失败!\n" ));
		return Status;
	}else {
		KdPrint(( "创建子键成功!\n" ));
	}
	
	//检查某项是否存在
	Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, REG_SOFTWARE_KEY_NAME );
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "子键不存在!\n" ));
		return Status;
	}else {
		KdPrint(( "子键存在!\n" ));
	}
	
	//写入REG_DWORD的数据
	ulValue = 100;
	Status = RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE, REG_SOFTWARE_KEY_NAME,
		L"DWORD_Value",REG_DWORD, &ulValue, sizeof(ulValue) );
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "写入子键失败!\n" ));
		return Status;
	}else {
		KdPrint(( "写入子键成功!\n" ));
	}
	
	//写入一个字符串
	Status = RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE,REG_SOFTWARE_KEY_NAME,
		L"SZ_Value",REG_SZ, SzString, wcslen(SzString)*2+2 );
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "写入字符串失败!\n" ));
		return Status;
	}else {
		KdPrint(( "写入字符串成功!\n" ));
	}

	//查询REG_DWORD的数据
	RtlQueryTab[0].Flags		= RTL_QUERY_REGISTRY_DIRECT;
	RtlQueryTab[0].Name		= L"DWORD_Value";
	RtlQueryTab[0].EntryContext	= &ulQueryValue;
	RtlQueryTab[0].DefaultType	= REG_DWORD;
	RtlQueryTab[0].DefaultData	= &ulDefaultData;
	RtlQueryTab[0].DefaultLength	= sizeof(ULONG);
	
	Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,REG_SOFTWARE_KEY_NAME,
				RtlQueryTab,NULL,NULL);
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "查询失败!\n" ));
		return Status;
	}else {
		KdPrint(( "查询成功, 值为%d!\n", ulQueryValue ));
	}
	
	//删除子键
	Status = RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE, REG_SOFTWARE_KEY_NAME,L"DWORD_Value");
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "删除子键失败!\n" ));
		return Status;
	}else {
		KdPrint(( "删除子键成功!\n" ));
	}
	return Status;
}
//===========================================================================
#pragma  code_seg( "INIT" )
NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUStrPath ) {
	
	CreateNewKey();		//创建新键值试验
	SetKeyValue();		//设置键值试验
	QueryValueInfo();	//查询键值试验
	EnumerateKeyValue();	//枚举键值和项测试
	DeleteKey();		//删除子项试验
	RtlRegister();		//Rtl系列函数试验
	return -2;
}

发表评论


Warning: Undefined variable $user_ID in /www/wwwroot/joenchen.com/wp-content/themes/agan/comments.php on line 66

您必须登录 才能进行评论。