从32位应用程序禁用Windows 7 64位上的智能卡即插即用 [英] Disabling Smart Card Plug and Play on Windows 7 64 bit from a 32 bit Application

查看:161
本文介绍了从32位应用程序禁用Windows 7 64位上的智能卡即插即用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了创建NULL CSP

对于Windows 7中不支持的智能卡,请点击此处:

http ://support.microsoft.com/kb/976832


$
我省去了大部分的"寻找卡片"。和UUID作为


卡名称的一部分,因为它实际上不应该是必要的(MSDN中没有任何内容说明它是)。



我可以检查注册表,看起来相应的条目是生成的
,但即使按照这个程序,当我插入

卡,Windows仍然在寻找驱动程序。



这些卡片如下:



GemAlto GemClub备注:ATR = 3B025301

Atmel AT88SC0104C:ATR = 3BB211000800001

Atmel AT88SC0204C:ATR = 3BB2110010800002

Atmel AT88SC0404C:ATR = 3BB2110010800004

Atmel AT88SC0808C:ATR = 3BB2110010800008

Atmel AT88SC1616C:ATR = 3BB2110010800016

Atmel AT88SC3216C:ATR = 3BB3110000000032

Atmel AT88SC6416C:ATR = 3BB3110000000064

Atmel AT88SC12816C:ATR = 3BB3110000000128

Atmel AT88SC25616C:ATR = 3BB3110000000256
$


这些卡都不是真正的智能卡。他们使用T = 0协议,有一个
ATR,并使用普通的PC / SC APDU进行通信,但他们没有文件

结构,加密等。就像一张真正的智能卡。此外,无论是GemAlto还是
Atmel都没有向Microsoft提交过null驱动程序,他们也没有计划从我们能够收集到的




到目前为止,我一直在指示我们的客户使用策略编辑器禁用智能卡插件和
播放功能,但是这个实际上并不是一个可行的b
解决方案。



这是我的代码(我用Delphi编程,但它应该很容易阅读):



const MemoATR:TATR =(数量:4;数据:($ 3B,$ 02,$ 53,$ 01,$ 00,

$ 00,$ 00,$ 00,$ 00);姓名:'GemClub Memo');

Atmel0104ATR:TATR =(数量:8;数据:($ 3B,$ B2,$ 11,$ 00,$ 10,

$ 80,$ 00,$ 01,$ 00);名称:'Atmel 0104');

Atmel0204ATR:TATR =(数量:8;数据:($ 3B,$ B2,$ 11,$ 00,$ 10,

$ 80,$ 00,$ 02,$ 00);名称:'Atmel 0204');

Atmel0404ATR:TATR =(数量:8;数据:($ 3B,$ B2,$ 11,$ 00,$ 10,

$ 80,$ 00,$ 04,$ 00);名称:'Atmel 0404');

Atmel0808ATR:TATR =(数量:8;数据:($ 3B,$ B2,$ 11,$ 00,$ 10,

$ 80,$ 00,$ 08,$ 00);名称:'Atmel 0808');

Atmel1616ATR:TATR =(数量:8;数据:($ 3B,$ B2,$ 11,$ 00,$ 10,

$ 80,$ 00,$ 16,$ 00);名称:'Atmel 1616');

Atmel3216ATR:TATR =(数量:8;数据:($ 3B,$ B3,$ 11,$ 00,$ 00,

$ 00,$ 00,$ 32,$ 00);名称:'Atmel 3216');

Atmel6416ATR:TATR =(数量:8;数据:($ 3B,$ B3,$ 11,$ 00,$ 00,

$ 00,$ 00,$ 64,$ 00);名称:'Atmel 6416');

Atmel12816ATR:TATR =(数量:8;数据:($ 3B,$ B3,$ 11,$ 00,$ 00,

$ 00,$ 01,$ 28,$ 00);名称:'Atmel 12816');

Atmel25616ATR:TATR =(数量:8;数据:($ 3B,$ B3,$ 11,$ 00,$ 00,

$ 00,$ 02,$ 56,$ 00);名称:'Atmel 25616');



//这是在引入系统时作为卡的价格提供的价值。这是以
//为单位提供的,以便为此
//卡禁用智能卡即插即用。

const CARD_CSP ='$ DisableSCPnP $';



函数RegisterCardNullCSP(ATR:TATR):LongInt;

Var SC:SCARDCONTEXT;

返回:LongInt;

卡:PChar;

CardsSize:LongWord;

CardFound:布尔值;

ContextOk:布尔值;

开头

CardFound:= False;

返回:= SCardEstablishContext(SCARD_SCOPE_SYSTEM,nil,nil,

LPSCARDCONTEXT(@SC));

ContextOk:=(Return = SCARD_S_SUCCESS);

如果ContextOk然后是
开始

//确定ATR是否已经存在于智能卡数据库中

CardsSize := 0;

返回:= SCardListCards(SC,LPCBYTE(@ ATR.Data [0]),nil,0,nil,

CardsSize);
如果Return = SCARD_S_SUCCESS则为
然后为
如果CardsSize>则开始为
1然后//空列表仍然返回大小1为NULL

终止

开始

卡片:= StrAlloc(CardsSize);

返回:= SCardListCards(SC,LPCBYTE(@ ATR.Data [0]),nil,0,Cards,

CardsSize);
如果Return = SCARD_S_SUCCESS则为
然后为
如果StrPas(卡片)= ATR.Name则开始

然后是
CardFound: =真;

结束;

StrDispose(卡片);

结束;

结束;

结束;



如果不是CardFound则为
开始

//将卡片引入系统

结果:= SCardIntroduceCardType(SC,PChar(ATR.Name),nil,nil,0,

LPCBYTE(@ ATR.Data [0]),nil,ATR.Count);

//如果Result = SCARD_S_SUCCESS则设置提供者名称为
然后为
结果:= SCardSetCardTypeProviderName(SC,PChar(ATR.Name),

SCARD_PROVIDER_CSP,CARD_CSP);

结束;



//清理资源

如果ContextOk则为
SCardReleaseContext(SC);



结果:=返回;

结束;



RegisterCardNullCSP(MemoATR);

RegisterCardNullCSP(Atmel0104ATR);

RegisterCardNullCSP(Atmel0204ATR);

RegisterCardNullCSP(Atmel0404ATR);

RegisterCardNullCSP(Atmel0808ATR);

RegisterCardNullCSP(Atmel1616ATR);

RegisterCardNullCSP(Atmel3216ATR);

RegisterCardNullCSP(Atmel6416ATR);

RegisterCardNullCSP(Atmel12816ATR);

RegisterCardNullCSP(Atmel25616ATR);



运行此代码后,我的注册表如下所示:

Windows注册表编辑器版本5.00

[HKEY_LOCAL_MACHINE \ SOFTWARE \Wow6432Node\Microsoft\Cryptography\Calais \SmartCards]


[HKEY_LOCAL_MACHINE\SOFTWARE \Wow6432Node\Microsoft\Cryptography\Calais\ SmartCards\Atmel 0104]


"ATR"= hex:3b,b2,11,00,10,80,00,01

" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Amelmel 0204]


" ATR" = hex:3b,b2,11,00,10,80,00,02
$
" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Amel 0404]


" ATR" = hex:3b,b2,11,00,10,80,00,04
$
" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Amel 0808]


" ATR" = hex:3b,b2,11,00,10,80,00,08
$
" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 12816]


" ATR" = hex:3b,b3,11,00,00,00,01,28
$
" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 1616]


" ATR" = hex:3b,b2,11,00,10,80,00,16
$
" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 25616]


" ATR" = hex:3b,b3,11,00,00,00,02,56
$
" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Amelmel 3216]


" ATR" = hex:3b,b3,11,00,00,00,00,32
$
" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Amelmel 6416]


" ATR" = hex:3b,b3,11,00,00,00,00,64
$
" Crypto Provider" =" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\GemClub备忘录]


" ATR" = hex:3b,02,53,01
$
"Crypto Provider"=" $ DisableSCPnP $"

[HKEY_LOCAL_MACHINE\SOFTWARE \Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Identity Device(Microsoft Generic Profile)]


"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"


"智能卡密钥存储提供商"="Microsoft智能卡密钥存储提供商"


" 80000001" =" msclmd.dll"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Identity Device(NIST SP 800-73 [PIV])]


"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"


"智能卡密钥存储提供商"="Microsoft智能卡密钥存储提供商"


" 80000001" =" msclmd.dll"



有趣的是,64位部分没有这些条目,看起来像是这样的b $ b:b
Windows注册表编辑器版本5.00



[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards]

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft &\\Cryptography \ Carais \SmartCards \Identity Device(Microsoft Generic Profile)]


" Crypto Provider"" Microsoft Base Smart Card Crypto Provider"


"智能卡密钥存储提供商"="Microsoft智能卡密钥存储提供商"


" 80000001" =" msclmd.dll"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Identity Device(NIST SP 800-73 [PIV])]


"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"


"智能卡密钥存储提供商"="Microsoft智能卡密钥存储提供商"


" 80000001" =" msclmd.dll"



在正常的64位区域内手动创建注册表项的工作量为预期的b
,这些卡不再提示给驱动程序。但我不相信我的

应用程序将有权在代码中执行此操作。



我的代码是32位,所以这些条目只出现在32位注册表中是可以理解的,但最终的结果是操作系统不是没有找到CSP,所以知识库文章几乎没用。 


$
有没有人知道如何从32位代码影响64位数据库而不必拥有我不太可能拥有的权限?



Jeff。

I have implemented the core portions of the procedure for creating a NULL CSP
for unsupported smart cards in Windows 7 found here:
http://support.microsoft.com/kb/976832

I dispensed with much of the "look for a card" and the UUID as part of the
card name, as it really shouldn't be necessary (nothing in the MSDN
description indicated it was).

I can check the registry, and it looks like the appropriate entries are
being produced, but even after following this procedure, when I insert the
card, Windows still looks for a driver.

The cards are as follows:

GemAlto GemClub Memo: ATR = 3B025301
Atmel AT88SC0104C : ATR = 3BB211000800001
Atmel AT88SC0204C : ATR = 3BB2110010800002
Atmel AT88SC0404C : ATR = 3BB2110010800004
Atmel AT88SC0808C : ATR = 3BB2110010800008
Atmel AT88SC1616C : ATR = 3BB2110010800016
Atmel AT88SC3216C : ATR = 3BB3110000000032
Atmel AT88SC6416C : ATR = 3BB3110000000064
Atmel AT88SC12816C : ATR = 3BB3110000000128
Atmel AT88SC25616C : ATR = 3BB3110000000256

None of these cards are true smart cards. They use T=0 protocol, have an
ATR, and use normal PC/SC APDUs to communicate, but they don't have file
structures, crypto, etc. like a true smart card. Also, neither GemAlto nor
Atmel has submitted a null driver to Microsoft, nor do they plan to, from
what I have been able to gather.

So far, I've been instructing our clients to disable the smart card plug and
play function with the policy editor, but this is not really a viable
solution.

Here is my code (I program with Delp but it should be easily readable):

const MemoATR : TATR = (Count: 4; Data : ($3B, $02, $53, $01, $00,
$00, $00, $00, $00); Name: 'GemClub Memo');
Atmel0104ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $01, $00); Name: 'Atmel 0104');
Atmel0204ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $02, $00); Name: 'Atmel 0204');
Atmel0404ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $04, $00); Name: 'Atmel 0404');
Atmel0808ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $08, $00); Name: 'Atmel 0808');
Atmel1616ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $16, $00); Name: 'Atmel 1616');
Atmel3216ATR : TATR = (Count: 8; Data : ($3B, $B3, $11, $00, $00,
$00, $00, $32, $00); Name: 'Atmel 3216');
Atmel6416ATR : TATR = (Count: 8; Data : ($3B, $B3, $11, $00, $00,
$00, $00, $64, $00); Name: 'Atmel 6416');
Atmel12816ATR : TATR = (Count: 8; Data : ($3B, $B3, $11, $00, $00,
$00, $01, $28, $00); Name: 'Atmel 12816');
Atmel25616ATR : TATR = (Count: 8; Data : ($3B, $B3, $11, $00, $00,
$00, $02, $56, $00); Name: 'Atmel 25616');

// This is the name that will be provided as the CSP for
// the card when introduced to the system. This is provided
// in order to disable Smart Card Plug and Play for this
// card.
const CARD_CSP = '$DisableSCPnP$';

Function RegisterCardNullCSP(ATR: TATR): LongInt;
Var SC: SCARDCONTEXT;
Return : LongInt;
Cards : PChar;
CardsSize : LongWord;
CardFound : Boolean;
ContextOk : Boolean;
Begin
CardFound := False;
Return := SCardEstablishContext(SCARD_SCOPE_SYSTEM, nil, nil,
LPSCARDCONTEXT(@SC));
ContextOk := (Return = SCARD_S_SUCCESS);
if ContextOk then
Begin
// Determine if the ATR is already in the Smart Card Database
CardsSize := 0;
Return := SCardListCards(SC, LPCBYTE(@ATR.Data[0]), nil, 0, nil,
CardsSize);
if Return = SCARD_S_SUCCESS then
Begin
if CardsSize > 1 then // Empty list still returns size 1 for the NULL
termination
Begin
Cards := StrAlloc(CardsSize);
Return := SCardListCards(SC, LPCBYTE(@ATR.Data[0]), nil, 0, Cards,
CardsSize);
if Return = SCARD_S_SUCCESS then
Begin
if StrPas(Cards) = ATR.Name then
CardFound := True;
End;
StrDispose(Cards);
End;
End;
End;

if Not CardFound then
Begin
// Introduce the card to the system
Result := SCardIntroduceCardType(SC, PChar(ATR.Name), nil, nil, 0,
LPCBYTE(@ATR.Data[0]), nil, ATR.Count);
// Set the provider name
if Result = SCARD_S_SUCCESS then
Result := SCardSetCardTypeProviderName(SC, PChar(ATR.Name),
SCARD_PROVIDER_CSP, CARD_CSP);
End;

// Cleanup resources
if ContextOk then
SCardReleaseContext(SC);

Result := Return;
End;

RegisterCardNullCSP(MemoATR);
RegisterCardNullCSP(Atmel0104ATR);
RegisterCardNullCSP(Atmel0204ATR);
RegisterCardNullCSP(Atmel0404ATR);
RegisterCardNullCSP(Atmel0808ATR);
RegisterCardNullCSP(Atmel1616ATR);
RegisterCardNullCSP(Atmel3216ATR);
RegisterCardNullCSP(Atmel6416ATR);
RegisterCardNullCSP(Atmel12816ATR);
RegisterCardNullCSP(Atmel25616ATR);

After running this code, my registry looks like this:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 0104]
"ATR"=hex:3b,b2,11,00,10,80,00,01
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 0204]
"ATR"=hex:3b,b2,11,00,10,80,00,02
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 0404]
"ATR"=hex:3b,b2,11,00,10,80,00,04
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 0808]
"ATR"=hex:3b,b2,11,00,10,80,00,08
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 12816]
"ATR"=hex:3b,b3,11,00,00,00,01,28
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 1616]
"ATR"=hex:3b,b2,11,00,10,80,00,16
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 25616]
"ATR"=hex:3b,b3,11,00,00,00,02,56
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 3216]
"ATR"=hex:3b,b3,11,00,00,00,00,32
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 6416]
"ATR"=hex:3b,b3,11,00,00,00,00,64
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\GemClub Memo]
"ATR"=hex:3b,02,53,01
"Crypto Provider"="$DisableSCPnP$"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Identity Device (Microsoft Generic Profile)]
"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
"80000001"="msclmd.dll"
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Identity Device (NIST SP 800-73 [PIV])]
"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
"80000001"="msclmd.dll"

Interestingly, the 64 bit section does not have these entries, it looks like
this:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Identity Device (Microsoft Generic Profile)]
"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
"80000001"="msclmd.dll"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Identity Device (NIST SP 800-73 [PIV])]
"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
"80000001"="msclmd.dll"

Manually creating the registry keys in the normal 64 bit area works as
expected, the cards are no longer prompt for drivers. But I don't believe my
app will have permissions to do this in code.

My code is 32 bit, so it is understandable that the entries only appear in the 32 bit registry, but the end result is that the OS isn't looking there for the CSP, so the knowledgebase article is pretty much useless. 

Does anyone know how I can affect the 64 bit database from 32 bit code without having to have privileges I'm not likely to have in the field?

Jeff.

推荐答案

您使用SCardIntroduceCardType编写的代码编写正确的注册表值,就像您期望的那样。你只需编写一个程序来设置注册表项(RegOpenKeyEx,...)

The code you wrote with SCardIntroduceCardType just write the right registry values, like you expect. You just have to write a program to set the registry keys (RegOpenKeyEx, ...)

然而,在64位机器上有一个32位程序的技巧注册表虚拟化。

However, there is a trick with 32bits program on 64bits machines with registry virtualization.

如果您使用的是64位系统,只需使用带有标志KEY_WOW64_64KEY的RegOpenKeyEx。

Just use RegOpenKeyEx with the flag KEY_WOW64_64KEY if you are on 64 bits systems.

以下是我用来了解这一点的代码:

Here is the code I use to know this :

BOOL Is64BitOS()

{

   BOOL bIs64BitOS = FALSE;



   //我们检查操作系统是否为64位

   typedef BOOL(WINAPI * LPFN_ISWOW64PROCESS)(HANDLE,PBOOL);



   LPFN_ISWOW64PROCESS

      fnIsWow64Process =(LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT(" kernel32"))," IsWow64Process");

 

   if(NULL!= fnIsWow64Process)

   {

      if(!fnIsWow64Process(GetCurrentProcess(),& bIs64BitOS))

      {

         //错误

      }¥b $ b   }¥b $ b  返回bIs64BitOS;

}

BOOL Is64BitOS()
{
   BOOL bIs64BitOS = FALSE;

   // We check if the OS is 64 Bit
   typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);

   LPFN_ISWOW64PROCESS
      fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
 
   if (NULL != fnIsWow64Process)
   {
      if (!fnIsWow64Process(GetCurrentProcess(),&bIs64BitOS))
      {
         //error
      }
   }
   return bIs64BitOS;
}

问候,

vincent


这篇关于从32位应用程序禁用Windows 7 64位上的智能卡即插即用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆