systeminfo卡死一例分析
1 故障现象
Win7 64位OS。设备与打印机窗口的进度条持续不能走完,此时打开设备管理器也依然卡住,systeminfo.exe程序也会卡住。此故障现象偶现难以复现。
2 systeminfo的dmp
鉴于另外两个进程的线程太多了,就优先从systeminfo进程入手研究。
给systeminfo进程下dmp,用windbg打开dmp,先查看每个线程的栈回溯:
. 0 Id: 1bb0.176c Suspend: 0 Teb: 000007ff`fffdd000 Unfrozen# Child-SP RetAddr Call Site
00 00000000`001ee498 000007fe`ff086ae6 ntdll!NtAlpcSendWaitReceivePort+0xa
01 00000000`001ee4a0 000007fe`ff081222 rpcrt4!LRPC_CCALL::SendReceive+0x156
02 00000000`001ee560 000007fe`fdd3f7e8 rpcrt4!I_RpcSendReceive+0x42
03 00000000`001ee590 000007fe`fdd3fa4b ole32!ThreadSendReceive+0x177 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 5147]
04 00000000`001ee5e0 000007fe`fdd3f78b ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+0x1cd [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4498]
05 00000000`001ee660 000007fe`fdbf745e ole32!CRpcChannelBuffer::SendReceive2+0x151 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4114]
06 00000000`001ee7f0 000007fe`fdbf73dc ole32!CAptRpcChnl::SendReceive+0xdb [d:\w7rtm\com\ole32\com\dcomrem\callctrl.cxx @ 603]
07 00000000`001ee8c0 000007fe`fdd3f1b5 ole32!CCtxComChnl::SendReceive+0x276 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 734]
08 00000000`001ee970 000007fe`ff12fd61 ole32!NdrExtpProxySendReceive+0x45 [d:\w7rtm\com\rpc\ndrole\proxy.cxx @ 1932]
09 00000000`001ee9a0 000007fe`fdd416c8 rpcrt4!NdrpClientCall2+0x9ea
0a 00000000`001ef110 000007fe`fdbf7252 ole32!ObjectStublessClient+0x206 [d:\w7rtm\com\rpc\ndrole\amd64\stblsclt.cxx @ 620]
0b 00000000`001ef4a0 000007fe`efb175df ole32!ObjectStubless+0x42 [d:\w7rtm\com\rpc\ndrole\amd64\stubless.asm @ 117]
0c 00000000`001ef4f0 00000000`ff37475c fastprox!CEnumProxyBuffer::XEnumFacelet::Next+0xd4
0d 00000000`001ef590 00000000`ff372969 systeminfo!CSystemInfo::LoadComputerInfo+0x1e0
0e 00000000`001ef6a0 00000000`ff3825b1 systeminfo!wmain+0x191
0f 00000000`001ef760 00000000`76df556d systeminfo!__wmainCRTStartup+0x13d
10 00000000`001ef7a0 00000000`7705372d kernel32!BaseThreadInitThunk+0xd
11 00000000`001ef7d0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d1 Id: 1bb0.139c Suspend: 0 Teb: 000007ff`fffdb000 Unfrozen# Child-SP RetAddr Call Site
00 00000000`01d4f708 00000000`7701332d ntdll!ZwWaitForMultipleObjects+0xa
01 00000000`01d4f710 00000000`76df556d ntdll!TppWaiterpThread+0x14d
02 00000000`01d4f9b0 00000000`7705372d kernel32!BaseThreadInitThunk+0xd
03 00000000`01d4f9e0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d2 Id: 1bb0.1dc4 Suspend: 0 Teb: 000007ff`fffd9000 Unfrozen# Child-SP RetAddr Call Site
00 00000000`0217fba8 00000000`770f97c4 ntdll!ZwWaitForWorkViaWorkerFactory+0xa
01 00000000`0217fbb0 00000000`76df556d ntdll!TppWorkerThread+0x304
02 00000000`0217fe40 00000000`7705372d kernel32!BaseThreadInitThunk+0xd
03 00000000`0217fe70 00000000`00000000 ntdll!RtlUserThreadStart+0x1d3 Id: 1bb0.a70 Suspend: 0 Teb: 000007ff`fffd7000 Unfrozen# Child-SP RetAddr Call Site
00 00000000`0230fc18 00000000`770f97c4 ntdll!ZwWaitForWorkViaWorkerFactory+0xa
01 00000000`0230fc20 00000000`76df556d ntdll!TppWorkerThread+0x304
02 00000000`0230feb0 00000000`7705372d kernel32!BaseThreadInitThunk+0xd
03 00000000`0230fee0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d4 Id: 1bb0.fd0 Suspend: 0 Teb: 000007ff`fffd5000 Unfrozen# Child-SP RetAddr Call Site
00 00000000`0224f9b8 000007fe`fd1c1203 ntdll!NtDelayExecution+0xa
01 00000000`0224f9c0 000007fe`fdbdd828 KERNELBASE!SleepEx+0xab
02 00000000`0224fa60 000007fe`fdbe16ee ole32!CROIDTable::WorkerThreadLoop+0x10 [d:\w7rtm\com\ole32\com\dcomrem\refcache.cxx @ 1345]
03 00000000`0224fa90 000007fe`fdbdd7da ole32!CRpcThread::WorkerLoop+0x1e [d:\w7rtm\com\ole32\com\dcomrem\threads.cxx @ 257]
04 00000000`0224fad0 00000000`76df556d ole32!CRpcThreadCache::RpcWorkerThreadEntry+0x1a [d:\w7rtm\com\ole32\com\dcomrem\threads.cxx @ 63]
05 00000000`0224fb00 00000000`7705372d kernel32!BaseThreadInitThunk+0xd
06 00000000`0224fb30 00000000`00000000 ntdll!RtlUserThreadStart+0x1d5 Id: 1bb0.5c0 Suspend: 0 Teb: 000007ff`fffd3000 Unfrozen# Child-SP RetAddr Call Site
00 00000000`028efc08 00000000`770f97c4 ntdll!ZwWaitForWorkViaWorkerFactory+0xa
01 00000000`028efc10 00000000`76df556d ntdll!TppWorkerThread+0x304
02 00000000`028efea0 00000000`7705372d kernel32!BaseThreadInitThunk+0xd
03 00000000`028efed0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
姑且猜测是0号线程,在等待应答,进而整个进程卡住。0号线程最后调用的是NtAlpcSendWaitReceivePort。这个api类似于网络socket的send和recv一体。它的声明如下:
NtAlpcSendWaitReceivePort(_In_ HANDLE PortHandle,_In_ ULONG Flags,_In_reads_bytes_opt_(SendMessage->u1.s1.TotalLength) PPORT_MESSAGE SendMessage,_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES SendMessageAttributes,_Out_writes_bytes_to_opt_(*BufferLength, *BufferLength) PPORT_MESSAGE ReceiveMessage,_Inout_opt_ PSIZE_T BufferLength,_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES ReceiveMessageAttributes,_In_opt_ PLARGE_INTEGER Timeout);
前四个参数是rcx=164h,rdx=20000h,r8=3,r9=46,后四个参数放在rsp+28h,rsp+30h,rsp+38h,rsp+40h。参数一是个表示Alpc Port的handle,用!handle
来翻译:
0:000> !handle 164
Handle 0000000000000164Type <Error retrieving type>
因为这个是进程dmp,翻译不了handle很正常。
3 动态调试systeminfo进程
我们已经有了故障Windows的C盘。所以考虑用调试器启动并观察Systeminfo,在NtAlpcSendWaitReceivePort处获取AlpcPort值。
用windbg打开systeminfo.exe,先给ntdll!NtAlpcSendWaitReceivePort下断点。
bp ntdll!NtAlpcSendWaitReceivePort "k";g
待断点触发后,sysinfo.pdb应该也载入了,此时可以给此处下断点:
bd 0;bp sysinfo!CSystemInfo::LoadComputerInfo+1dd;g
bd 0
是禁用原先的NtAlpcSendWaitReceivePort
断点,因为这个api频繁被调用到。
待1号断点触发后,再禁用1号断点,启用0号断点。
bd 1;be 0;g
此时得到的栈回溯,跟故障环境的systeminfo.dmp里的就几乎一样了。
Child-SP RetAddr Call Site
00000000`0017e778 000007fe`fe846ae6 ntdll!NtAlpcSendWaitReceivePort
00000000`0017e780 000007fe`fe841222 RPCRT4!LRPC_CCALL::SendReceive+0x156
00000000`0017e840 000007fe`ff12f7e8 RPCRT4!I_RpcSendReceive+0x42
00000000`0017e870 000007fe`ff12fa4b ole32!ThreadSendReceive+0x177 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 5147]
00000000`0017e8c0 000007fe`ff12f78b ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+0x1cd [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4498]
00000000`0017e940 000007fe`fefe745e ole32!CRpcChannelBuffer::SendReceive2+0x151 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4114]
00000000`0017ead0 000007fe`fefe73dc ole32!CAptRpcChnl::SendReceive+0xdb [d:\w7rtm\com\ole32\com\dcomrem\callctrl.cxx @ 603]
00000000`0017eba0 000007fe`ff12f1b5 ole32!CCtxComChnl::SendReceive+0x276 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 734]
00000000`0017ec50 000007fe`fe8efd61 ole32!NdrExtpProxySendReceive+0x45 [d:\w7rtm\com\rpc\ndrole\proxy.cxx @ 1932]
00000000`0017ec80 000007fe`ff1316c8 RPCRT4!NdrpClientCall2+0x9ea
00000000`0017f3f0 000007fe`fefe7252 ole32!ObjectStublessClient+0x206 [d:\w7rtm\com\rpc\ndrole\amd64\stblsclt.cxx @ 620]
00000000`0017f780 000007fe`f09075df ole32!ObjectStubless+0x42 [d:\w7rtm\com\rpc\ndrole\amd64\stubless.asm @ 117]
00000000`0017f7d0 00000000`ff0f475c fastprox!CEnumProxyBuffer::XEnumFacelet::Next+0xd4
00000000`0017f870 00000000`ff0f2969 sysinfo!CSystemInfo::LoadComputerInfo+0x1e0
00000000`0017f980 00000000`ff1025b1 sysinfo!wmain+0x191
00000000`0017fa40 00000000`76cf556d sysinfo!__wmainCRTStartup+0x13d
00000000`0017fa80 00000000`76f5372d kernel32!BaseThreadInitThunk+0xd
00000000`0017fab0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
此时的rcx=15ch,rdx=20000h,r8=299d10h,r9=2a8208h。
0:000> !handle 15c f
Handle 15cType ALPC PortAttributes 0GrantedAccess 0x1f0000:Delete,ReadControl,WriteDac,WriteOwner,SynchNoneHandleCount 2PointerCount 8Name <none>No Object Specific Information available
这个参数一的确是ALPC Port。在进程调试的时候就可以用!handle
翻译出来。
3 从内核数据分析这些ALPC对象
windbg有命令!alpc
可以查看alpc的内核对象,端口的所有者,alpc信息的明细。但是要在内核层的数据中查看。此时可以用内核调试的方法,或者用livekd(参见https://blog.csdn.net/u010607621/article/details/120421591)。
在内核dmp中,先找到systeminfo进程,再将进程上下文切换到此进程:
0: kd> !process 0 0 systeminfo.exe
PROCESS fffffa80ce65f610SessionId: 1 Cid: 0e28 Peb: 7fffffdf000 ParentCid: 1f30DirBase: 1414bb000 ObjectTable: fffff8a00cee1580 HandleCount: 95.Image: systeminfo.exe
0: kd> .PROCESS fffffa80ce65f610
Implicit process is now fffffa80`ce65f610
此时,就可以翻译handle了:
0: kd> !handle 15c 37PROCESS fffffa80ce65f610SessionId: 1 Cid: 0e28 Peb: 7fffffdf000 ParentCid: 1f30DirBase: 1414bb000 ObjectTable: fffff8a00cee1580 HandleCount: 95.Image: systeminfo.exeHandle table at fffff8a00c8a2000 with 95 entries in use015c: Object: fffffa80cc6fe620 GrantedAccess: 001f0001 Entry: fffff8a00c10b570
Object: fffffa80cc6fe620 Type: (fffffa80c7c6e8c0) ALPC PortObjectHeader: fffffa80cc6fe5f0 (new version)HandleCount: 1 PointerCount: 6
使用windbg的!alpc
命令观察这个alpc port:
0: kd> !alpc /p fffffa80cc6fe620
Port @ fffffa80cc6fe620Type : ALPC_CLIENT_COMMUNICATION_PORTCommunicationInfo : fffff8a00b839510ConnectionPort : fffffa80cff1f090ClientCommunicationPort : fffffa80cc6fe620ServerCommunicationPort : fffffa80cf9f0790OwnerProcess : fffffa80ce65f610 (systeminfo.exe)SequenceNo : 0x00000016 (22)CompletionPort : 0000000000000000CompletionList : 0000000000000000MessageZone : 0000000000000000ConnectionPending : NoConnectionRefused : NoDisconnected : NoClosed : NoFlushOnClose : YesReturnExtendedInfo : NoWaitable : NoSecurity : StaticWow64CompletionList : NoMain queue is empty.Large message queue is empty.Pending queue has 1 message(s)fffff8a00df219c0 00000464 00000000000015e0:0000000000001240 0000000000000000 0000000000000000 LPC_REPLYCanceled queue is empty.
此alpc port实际是个ClientCommunicationPort,类似于tcp port里面的client端口。此例的server port是fffffa80cf9f0790
。用!alpc /p fffffa80cf9f0790
可知这个server port的主人进程是svchost.exe -k netsvcs
。
4 查看alpc消息
回到systeminfo的进程调试,输入gu
,让NtAlpcSendWaitReceivePort
执行完毕:
0:000> gu
RPCRT4!LRPC_CCALL::SendReceive+0x156:
000007fe`fe846ae6 8bd8 mov ebx,eax
0:000> k
Child-SP RetAddr Call Site
00000000`0017e780 000007fe`fe841222 RPCRT4!LRPC_CCALL::SendReceive+0x156
00000000`0017e840 000007fe`ff12f7e8 RPCRT4!I_RpcSendReceive+0x42
00000000`0017e870 000007fe`ff12fa4b ole32!ThreadSendReceive+0x177 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 5147]
00000000`0017e8c0 000007fe`ff12f78b ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+0x1cd [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4498]
00000000`0017e940 000007fe`fefe745e ole32!CRpcChannelBuffer::SendReceive2+0x151 [d:\w7rtm\com\ole32\com\dcomrem\channelb.cxx @ 4114]
00000000`0017ead0 000007fe`fefe73dc ole32!CAptRpcChnl::SendReceive+0xdb [d:\w7rtm\com\ole32\com\dcomrem\callctrl.cxx @ 603]
00000000`0017eba0 000007fe`ff12f1b5 ole32!CCtxComChnl::SendReceive+0x276 [d:\w7rtm\com\ole32\com\dcomrem\ctxchnl.cxx @ 734]
00000000`0017ec50 000007fe`fe8efd61 ole32!NdrExtpProxySendReceive+0x45 [d:\w7rtm\com\rpc\ndrole\proxy.cxx @ 1932]
00000000`0017ec80 000007fe`ff1316c8 RPCRT4!NdrpClientCall2+0x9ea
00000000`0017f3f0 000007fe`fefe7252 ole32!ObjectStublessClient+0x206 [d:\w7rtm\com\rpc\ndrole\amd64\stblsclt.cxx @ 620]
00000000`0017f780 000007fe`f09075df ole32!ObjectStubless+0x42 [d:\w7rtm\com\rpc\ndrole\amd64\stubless.asm @ 117]
00000000`0017f7d0 00000000`ff0f475c fastprox!CEnumProxyBuffer::XEnumFacelet::Next+0xd4
00000000`0017f870 00000000`ff0f2969 sysinfo!CSystemInfo::LoadComputerInfo+0x1e0
00000000`0017f980 00000000`ff1025b1 sysinfo!wmain+0x191
00000000`0017fa40 00000000`76cf556d sysinfo!__wmainCRTStartup+0x13d
00000000`0017fa80 00000000`76f5372d kernel32!BaseThreadInitThunk+0xd
00000000`0017fab0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
查看参数七,看看收到的alpc消息包是什么:
0:000> dps rsp
*** ERROR: Module load completed but symbols could not be loaded for C:\PROGRA~2\RCC-Guest-Tool\64\RCD_AppInit.dll
00000000`0017e780 00000000`00000000
00000000`0017e788 00000000`002a0d60
00000000`0017e790 00000000`0017e970
00000000`0017e798 000007fe`fe85688f RPCRT4!LRPC_BIND_CCALL::NotifyBHStateChange+0x138
00000000`0017e7a0 00000000`00299d10
00000000`0017e7a8 00000000`0017e7d0
00000000`0017e7b0 00000000`002a8208
00000000`0017e7b8 00000000`00000000
00000000`0017e7c0 00000000`002a6ce8
00000000`0017e7c8 00000000`002a2e70
00000000`0017e7d0 00000000`00000048
00000000`0017e7d8 00000000`00000000
00000000`0017e7e0 00000000`00000000
00000000`0017e7e8 00000000`002a8378
00000000`0017e7f0 00000000`002a7d70
00000000`0017e7f8 000007fe`fe810000 RPCRT4!Server2003NegotiateDisable <PERF> (RPCRT4+0x0)
0:000> dt -r ole32!PORT_MESSAGE 299d10+0x000 u1 : _PORT_MESSAGE::<unnamed-type-u1>+0x000 s1 : _PORT_MESSAGE::<unnamed-type-u1>::<unnamed-type-s1>+0x000 DataLength : 0n32+0x002 TotalLength : 0n72+0x000 Length : 0x480020+0x004 u2 : _PORT_MESSAGE::<unnamed-type-u2>+0x000 s2 : _PORT_MESSAGE::<unnamed-type-u2>::<unnamed-type-s2>+0x000 Type : 0n8194+0x002 DataInfoOffset : 0n0+0x000 ZeroInit : 0x2002+0x008 ClientId : _CLIENT_ID+0x000 UniqueProcess : 0x00000000`000015e0 Void+0x008 UniqueThread : 0x00000000`00001240 Void+0x008 DoNotUseThisField : 2.7667676167109806e-320 +0x018 MessageId : 0x464+0x020 ClientViewSize : 0xd926b+0x020 CallbackId : 0xd926b
可以看到这个消息包是由pid=15e0进程(刚刚那个svchost)里的tid=1240线程处理的。
用procexp看看这个线程的栈回溯,线程入口大概是TppWorkerThread
。只是一个很普通的系统线程池入口。不知道如何判别它是因为什么业务请求而创建的线程。
用!alpc /m
可以查看这个消息包的具体内容:
0: kd> !alpc /m 464Message @ fffff8a00df219c0MessageID : 0x0464 (1124)CallbackID : 0xD926B (889451)SequenceNumber : 0x00000016 (22)Type : LPC_REPLYDataLength : 0x0020 (32)TotalLength : 0x0048 (72)Canceled : NoRelease : YesReplyWaitReply : NoContinuation : YesOwnerPort : fffffa80cff1f090 [ALPC_CONNECTION_PORT]WaitingThread : 0000000000000000QueueType : ALPC_MSGQUEUE_PENDINGQueuePort : fffffa80cc6fe620 [ALPC_CLIENT_COMMUNICATION_PORT]QueuePortOwnerProcess : fffffa80ce65f610 (systeminfo.exe)ServerThread : 0000000000000000QuotaCharged : NoCancelQueuePort : 0000000000000000CancelSequencePort : 0000000000000000CancelSequenceNumber : 0x00000000 (0)ClientContext : 00000000002a80e0ServerContext : 0000000000000000PortContext : 000000000000015cCancelPortContext : 0000000000000000SecurityData : 0000000000000000View : fffff8a00a549e20
5 后续
svchost -k netsvcs
进程包含不少服务。
如果还有发生此类卡死,可强制关闭svchost进程看看。
systeminfo卡死一例分析相关推荐
- stella forum v1.2 用例分析
最近一直在看<uml与模式应用>,想把里面的ooa/d思想应用到下一版的stella forum中,按照里面统一过程的思想,先要做用例分析,嘿嘿,于是就有了下面这个昨天写的用户的帖子操作的 ...
- Makefile 实际用例分析(一) ------- 比较通用的一种架构
这里不再说Makefile的基本知识,如果需要学习,那么请参考: 下载:makefile 中文手册 或者 点击打开链接 或者 跟我一起写Makefile( 陈皓 ) 这里说的是一般的实际的一个工程应该 ...
- 需求用例分析之九:序列图
作者:张克强 作者微博:张克强-敏捷307 序列图,也称时序图.顺序图,英文名Sequence Diagram.在雅各布森用例分析方法中鼓励使用各类图形来表达,但恰恰没有明确提到序列图.而科伯恩 ...
- 苍狼敏捷需求用例分析方法简介并讲义下载
作者:张克强 作者微博:张克强-敏捷307 用例分析方法已经有不短的历史,发展出了多种用例分析方法.笔者花费了大量时间,对用例分析的各个方面进行实践和分析,得到如下系列文章: 需求用例分析之一: ...
- 需求用例分析之七:业务用例之小结
作者:张克强 作者微博:张克强-敏捷307 RUP虽然对于业务对象建模进行了详细的说明,但其本身并没有把业务对象建模(领域模型).业务用例作为必须的工件.Rational系方法把业务用例作为需求 ...
- 需求用例分析之八:用例颗粒度
作者:张克强 作者微博:张克强-敏捷307 RUP系的考虑 在RUP中,没有对用例的颗粒度给出清晰的指导.2004年Rational 中国区技术销售经理 傅纯一发表一文<用例建模指南> ...
- 需求用例分析之四:业务规则
作者:张克强 作者微博:张克强-敏捷307 在雅各布森用例分析方法和科伯恩用例分析方法中用例本身其实都没有"业务规则"的属性.但是业界使用中常常会给用例加上这个属性,这是为什么呢? ...
- 需求用例分析之三:补充规约
补充规约在RUP中是记录那些在用例模型的用例中不容易体现出来的系统需求.这些需求包括: § 法律法规方面的需求和应用标准. § 要建立的系统质量属性,包括可用性需求.可靠性需求.性能需求和可支持性需求 ...
- 需求用例分析之二:级别设置
在<编写有效用例>(阿莱斯特-科伯恩著,以下用科伯恩用例来指代)一书中,赋予了用例不同的级别,科伯恩形象的设定了如下级别:海平面.云朵.风筝.蛤等等. 科伯恩建议用例级别分为多个个目标层次 ...
最新文章
- 软件开发经验总结(一)细节决定软件的成败
- 结合实例与代码谈数字图像处理都研究什么?
- Node.js aitaotu图片批量下载Node.js爬虫1.00版
- 设计过程中常见的 10 个小问题
- android网络编程——HttpGet、HttpPost比较
- js实现代码类似w3School演示效果
- 如何在SAP Spartacus category 页面里拿到当前的category信息
- c语言中 字符串常量的界定符,c语言题库2
- Maven搭建springMvc+myBatis完整项目
- 一个程序员的创业失败教训【转自CSDN】
- TCP/IP协议 TCP包深入理解
- runtime之ivar内存布局篇
- Pytorch——计算机视觉工具包:torchvision
- 无法读源文件或磁盘_拯救动态磁盘的一些尝试
- python列表del_python删除列表元素的三种方法(remove,pop,del)
- Arcgis选择自己想要的区域地图
- android随机抽奖代码_基于JavaScript实现抽奖系统
- 计算机科学与技术专业考数媒,数字媒体技术研究生院校排名
- Word 安装Mathtype后无法使用CTRL+C和CTRL+V【一次性解决】
- 解决 Chrome浏览器网页上出现光标,无法通过键盘方向键实现页面滚动的问题