微软的桌面版 Power BI 也是基于CEF开发的!
Windows统治客户端的年代 在Web大潮涌动近20年之后 几近结束。
2017/02/13
2011/05/06
How to create a MS Windows local account by program
There are several ways to make it happen:
- PowerShell solution: http://stackoverflow.com/questions/383390/create-local-user-with-powershell-windows-vista
- .Net solution: http://msdn.microsoft.com/en-us/library/bb384369.aspx#Y200
- Using Active Directory Service Interfaces (ADSI) COM: http://msdn.microsoft.com/en-us/library/aa705985(v=vs.85).aspx
2010/03/15
My First Perl XS module
In recent days, I created my first Perl XS module -- Perl Win32::Oleaccxs.
Win32::Oleaccxs is a module which depended on Microsoft Active Accessibility UI API to go through all the GUI widgets in Microsoft Windows system. This module is just a simple wrapper to the client APIs. By using this module, you can navigate most of the Windows GUI widgets by using Perl.
This is very early version -- v0.01, It is undocumented yet. I will finish the document and upload it to CPAN some times later. :)
Win32::Oleaccxs is a module which depended on Microsoft Active Accessibility UI API to go through all the GUI widgets in Microsoft Windows system. This module is just a simple wrapper to the client APIs. By using this module, you can navigate most of the Windows GUI widgets by using Perl.
This is very early version -- v0.01, It is undocumented yet. I will finish the document and upload it to CPAN some times later. :)
2010/02/08
sub GetTreeViewItemRect of Win32::GuiTest functions
Win32::GuiTest is a powerful tool for Windows GUI testing. I love it! This is a small function which allow GuiTest to send Mouse Events to the item inside TreeCtrl.
#!/usr/bin/perl
## Initially generated by Win32-GuiTest Recorder (v1.03)
## Pragmas/Directives
use strict;
use warnings;
use 5.010;
## Imports
use Win32::GuiTest qw/:ALL/;
$Win32::GuiTest::debug = 0; # Set to "1" to enable debug output.
use constant {
TVM_EXPAND => 0x1100 + 2,
TVM_GETITEMRECT => 0x1100 + 4,
TVM_GETNEXTITEM => 0x1100 + 10,
TVM_SELECTITEM => 0x1100 + 11,
TVM_GETITEM => 0x1100 + 12,
TVM_ENSUREVISIBLE => 0x1100 + 20,
TVGN_ROOT => 0,
TVGN_NEXT => 1,
TVGN_CHILD => 4,
TVGN_CARET => 9,
TVE_EXPAND => 2,
};
=item
Helper function to go through Items inside TreeCtrl.
It is as same as the internal function of Win32::GuiTest
But it allows to use REGEX as the item name
=cut
sub xTVPathWalk
{
my $hwnd = shift;
my $tvitem = shift;
my $text_buf = shift;
my $hItem = shift;
my $max_buf = shift;
my $delay = shift;
my @parts = @_;
SendMessage( $hwnd, TVM_ENSUREVISIBLE(), 0, $hItem );
while( $hItem != 0 ){
my $str_long = pack( "L L L L L L L L L L",
0x41, #mask (TVIF_TEXT | TVIF_CHILDREN)
$hItem, #hItem
0, #state
0, #stateMask
$text_buf->{ 'ptr' }, #pszText
100, #cchTextMax
0, #iImage
0, #iSelectedImage
0, #cChildren
0 #lParam
);
WriteToVirtualBuffer( $tvitem, $str_long );
SendMessage( $hwnd, TVM_GETITEM(), 0, $tvitem->{ 'ptr' } );
my $text = ReadFromVirtualBuffer( $text_buf, $max_buf );
$text =~ s/\0.+$//;
my $struct = ReadFromVirtualBuffer( $tvitem, 40 );
my @fields = unpack( "L10", $struct );
my $titlere = $parts[0];
if( $text =~ /$titlere/i ){
SendMessage( $hwnd, TVM_EXPAND(), TVE_EXPAND(), $hItem );
#
# Give the node some time to expand...
#
select(undef, undef, undef, $delay) if $delay;
if( @parts == 1 ){
return $hItem;
}
if( $fields[ 8 ] ){
my $hChild = SendMessage( $hwnd,
TVM_GETNEXTITEM(),
TVGN_CHILD(),
$hItem );
shift( @parts );
return xTVPathWalk( $hwnd,
$tvitem,
$text_buf,
$hChild,
$max_buf,
$delay,
@parts );
}
}else{
$hItem = SendMessage( $hwnd,
TVM_GETNEXTITEM(),
TVGN_NEXT(),
$hItem );
}
}
return 0;
}
=item GetTreeViewItemRect
Return the RECT of Item related to Screen.
Parameters are as same parameters as SelTreeViewItem
=cut
sub GetTreeViewItemRect
{
my $hwnd = shift;
my $path = shift;
my $max_buf = shift;
my $delay = shift;
if( !$max_buf ){
$max_buf = 124;
}
if( !$delay ){
$delay = 0.50;
}
my @parts = split( /\|/, $path );
my $tvitem;
eval{
$tvitem = AllocateVirtualBuffer( $hwnd, 50 );
};
if( $@ ){
die "Allocation failed with message ---> $@";
}
my $text_buf = AllocateVirtualBuffer( $hwnd, $max_buf );
my $item_rect = AllocateVirtualBuffer( $hwnd, 16 );
my $hItem = SendMessage( $hwnd, TVM_GETNEXTITEM(), TVGN_ROOT(), 0 );
$hItem = xTVPathWalk( $hwnd,
$tvitem,
$text_buf,
$hItem,
$max_buf,
$delay,
@parts );
SendMessage( $hwnd, TVM_SELECTITEM(), TVGN_CARET(), $hItem );
my @rect = (0, 0, 0, 0);
if ($hItem) { # TVM_GETITEMRECT = 0x1104
say "Got the item: $hItem";
SendMessage( $hwnd, TVM_ENSUREVISIBLE(), 0, $hItem );
WriteToVirtualBuffer( $item_rect, pack('L L L L', $hItem, 0, 0, 0));
if (SendMessage ( $hwnd, TVM_GETITEMRECT(), 1, $item_rect->{ 'ptr' } ) ) {
@rect = unpack('L4', ReadFromVirtualBuffer( $item_rect, 16 ) );
}
}
FreeVirtualBuffer( $item_rect );
FreeVirtualBuffer( $tvitem );
FreeVirtualBuffer( $text_buf );
@rect[0,1] = ClientToScreen( $hwnd, $rect[0], $rect[1] );
@rect[2,3] = ClientToScreen( $hwnd, $rect[2], $rect[3] );
return @rect;
}
=item SendMouseToTreeViewItem($hwndTreectrl, $path, $mouseevents)
$hwndTrectrl - the HWND of TreeCtrl
$path - full path of TreeCtrl item
$mouseevents - mouse events, please refer to Win32::GuiTest::SendMouse
=cut
sub SendMouseToTreeViewItem {
my $hwnd = shift;
my $path = shift;
my @rect = GetTreeViewItemRect($hwnd, $path);
if ($rect[2] - $rect[0] != 0) {
MouseMoveAbsPix($rect[0] + 1, $rect[1] + 1);
SendMouse(shift);
}
}
Here is a exameple. It will find the first `Windows Explorer' window,
my @windows = FindWindowLike(undef,undef,"ExploreWClass");
if (scalar @windows) {
SetForegroundWindow($windows[0]);
SetActiveWindow($windows[0]);
my ($treectl) = FindWindowLike($windows[0], undef, 'SysTreeView32');
if ($treectrl) {
SendMouseToTreeViewItem($treectl, 'desktop|my computer|c:|perl', '{leftclick}{leftclick}')
}
}
2010/01/22
Windows Side-by-side Assemblies
From Visual Studio 2005, WinSxS became a mandatory things for Windows application. Especially when you depends on some common DLL components, for example, Common Controls, MS VC CRT, MS GdiPlus. All this need to be specified with the MANIFEST file.
It is a little noisily to generate the MANIFEST manually. So Microsoft do this for you. Indeed, the MANIFEST file was created by `link.exe'. In the C/C++ header file, it is using #pragma instrument to specify the DLL dependency explicitly.
For example MSVCRT: it is specified by 'crtdefs.h' and 'crtassem.h'.
Inside crtdefs.h, it defines the linker comment, like below:
and all the variants, e.g. __LIBRARIES_ASSEMBLY_NAME_PREFIX, __VCASSEMBLY_PUBLICKEYTOKEN, were defined inside `crtassem.h'.
It is a little noisily to generate the MANIFEST manually. So Microsoft do this for you. Indeed, the MANIFEST file was created by `link.exe'. In the C/C++ header file, it is using #pragma instrument to specify the DLL dependency explicitly.
For example MSVCRT: it is specified by 'crtdefs.h' and 'crtassem.h'.
Inside crtdefs.h, it defines the linker comment, like below:
#ifdef _DEBUG
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugCRT' " \
"version='" _CRT_ASSEMBLY_VERSION "' " \
"processorArchitecture='x86' " \
"publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".CRT' " \
"version='" _CRT_ASSEMBLY_VERSION "' " \
"processorArchitecture='x86' " \
"publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#endif
and all the variants, e.g. __LIBRARIES_ASSEMBLY_NAME_PREFIX, __VCASSEMBLY_PUBLICKEYTOKEN, were defined inside `crtassem.h'.
2009/12/14
通过虚拟机进行 Windows Kernel Debug
文介绍了硬件方式,这次来个更快的,通过虚拟机进行 Windows Kernel Debug。现在计算机硬件如此强大,我们完全可以把Target运行在一个虚拟机内,然后通过宿主机来调试。
首先,target——也就是虚拟机,也要进行同样的启动配置,让它进入debug模式。
其次,配置虚拟机程序,让它把target的COM端口 映射到一个命名管道。
以Virtual PC2007为例子,需要把Target的端口映射成一个 命名管道。其他的虚拟及程序如 VMWare 以及 VirtualBox也都有相应的设置。
然后,修改 windbg的参数,通过命名管道连接target
windbg -k com:pipe,port=\\.\pipe\com2,resets=0,reconnect
连接搞定!!!
效果和使用一个 单独的target计算机一样 :D
Windows Kernel Debug
Debug 对于程序开发来说是非常非常重要的手段。一个良好的Debug开发环境会让开发工作无往而不利。 对于 Microsoft Windows这样的庞然大物,内核开发的调试工作是非常有挑战性的。Windows 驱动程序开发,这些都需要进行内核级别的调试。当然,Microsoft的同志们,感触肯定比我们要多,因为他们每天都要在上面工作。
Microsoft实际上也已经作了大量的工作,对于Windows内核开发而言,内核的调试其实还是很简单的。

windbg -k com:port=Com1,baud=115200
1, 硬件环境准备
进行windows内核调试,原则上需要两台计算机:一个运行测试代码叫做target;另一个运行debugger 叫做 Host。在Target与Host之间需要 通讯连接。目前比较常见的有三种: 串口,USB, 和1394。 串口是最常见的,下面就以串口为例。
(from http://www.wd-3.com/archive/RemoteDbg.htm, Author: Jolyon Wright)
可以把 Host COM1 连接 Target COM1;也可以 Host COM2 连 Target COM1。
连接的时候不需要 一一对应。
2,Target 设置
所谓Target设置,其实就是打开Target计算机 Windows操作系统的调试选项。Windows都是内置内核调试功能的, 但是缺省关闭的。需要通过修改启动参数 (boot option) 打开。
对于Windows server 2003/XP/2000 操作系统,可以修改 Boot.ini 在启动项的后面加上
“/debug /debugport=COM2 /baudrate=115200”
看起来就象下面这样:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows XP Debug1" /fastdetect /debug /debugport=COM1 /baudrate=115200
这里 debugport 可以用COM1/2, Baudrate也可以作相应的调整 115200是不错的选择。
对于Windows Vista/2008/7 操作系统,需要使用 bcdedit来设置。这里需要两步:
第一: 打开debug
bcdedit /debug [on | off]
第二: 设置debug参数
bcdedit /dbgsettings SERIAL DEBUGPORT:2 BAUDRATE:115200
第二步其实可以跳过,系统缺省使用串口COM1, 速率:115200。
然后重新启动Target,进入调试模式。 其实在调试模式下,如果没有连上Debugger,系统运行起来就跟普通的系统差不多,可能会慢一些。
3, Host调试软件
Host 需要安装 Debugging Tools for Windows (http://www.microsoft.com/whdc/devtools/downloads.mspx)
安装完毕后,就可以使用Windbg连接 target。建议使用 6.11或更高的版本。
运行参数:
Windbg启动后应该显示:
Microsoft (R) Windows Debugger Version 6.1.0017.2
Copyright (c) Microsoft Corporation. All rights reserved.
Opened \\.\com1
Waiting to reconnect...
Copyright (c) Microsoft Corporation. All rights reserved.
Opened \\.\com1
Waiting to reconnect...
Target连接成功后应该显示:
Connected to Windows XP 2600 x86 compatible target, ptr64 FALSE
Kernel Debugger connection established.
Symbol search path is: \\Sysphus\softshared\symbols\KillerApp\sym;SRV*\\Sysphus\softshared\symbols\SymStore*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows XP Kernel Version 2600 MP (1 procs) Checked x86 compatible
Built by: 2600.xpsp1.020828-1920
Kernel Debugger connection established.
Symbol search path is: \\Sysphus\softshared\symbols\KillerApp\sym;SRV*\\Sysphus\softshared\symbols\SymStore*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows XP Kernel Version 2600 MP (1 procs) Checked x86 compatible
Built by: 2600.xpsp1.020828-1920
显示的内容会随着Target运行软件的版本而有些不同。
在windbg 通过 ctrl+break键 来中断 target,进入调试交互状态,这时候Target就像死了一样,别紧张,这是因为你再通过debugger来 控制它。
4, Host 配置Symbol Path
调试中有一个很重的步骤就是 Symbol,没有Symbol 在调试中寸步难行,我们只能面对一堆二进制代码。微软提供的Symbol支持方案配置很灵活,可以有本地symbol 也可以通过Symbol server, symbol cache。 关于symbol 在 Debugging Tools for Windows的 帮助文件中 专门有一个章节介绍: Debuggers >> Symbols
比较快捷的办法:下载 Windows Symbol Files;同时配置 Microsoft的symbol server。
A, 下载相应版本的 Windows Symbol Files http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx
安装到 一个位置:如 C:\WinSymbols
B, 在Windbg中设置 Symbol paths: File--> Symbol File Path 快捷方式(Ctrl+S)
设置path 为:
C:\WinSymbols;d:\OtherPath\To\the\build\pdb;srv*D:\Symbols*http://msdl.microsoft.com/download/symbols
这里D:\Symbols 是用来保存从 Microsoft symbol服务器下载回来的 pdb。
剩下的工作就是学习如何使用 windbg了。 :)
Goood luck~~~
2009/06/29
Small Skills of Command Prompt for Windows
There are some useful skills for CMD.exe in Windows.
1, How to do a substring in the CMD.exe -- %VAR_NAME:~POS,LEN%
for example
1, How to do a substring in the CMD.exe -- %VAR_NAME:~POS
for example
set name=fingercatecho %name:~6,3%
This will give you a "cat" ;)
2, How to get the input of user as a string?
On windows 2000 or later. It is simple.
set /p answer=Prompt Message Hereecho %answer%
This will give you the input stirng of user.
Windows Command Prompt (.bat) file never suppose to be a powerful shell. But Microsoft really give it more an more power until a real PowerShell came into place.
2009/02/25
Install Safari4 without installation on Windows
First, Extract the Safari.cab into a folder. The Safari.cab is from Safari.msi of SafariSetup.exe, you can open the .exe and .msi by using 7-zip tool. :D
Second, put the file into the right folder. If you have MinGW or Cygwin, you can use this script to move all the files into the right folder.
for i in *; do fp=${i//_/\/}; echo $fp; f=$(basename $fp); eval "p=\${fp%$f}"; if [ $fp != $f ];then if [ ! -d $p ];then mkdir -p $p; fi; mv $i $fp; fi; done
Now ready to go! Safari4 beta is a green software.
2007/01/17
Hack the IDLE.DLL of Yahoo Messenger
Yahoo Messenger is very nice IM software. But it used the very old window HOOK functions to detect the user idle time through IDLE.DLL. The idle.dll is a 6k DLL file which created with Microsoft VC 7.1 and linked with MSVCR71.DLL. In this way, the IDLE.DLL will be injected to all the user applications, and hook the message queue of all applications, and it will also injects the MSVCR71.DLL into the user applications. Please refer MSDN for details about the Windows HOOK function.
Yahoo Messenger 是一个很不错的IM软件。但是它是用了一个非常陈旧的Windows Hook功能,因此制造了一个idle.dll 用来来检测用户的发呆时间。这个IDLE.DLL 文件看起来并不大,只有6k,其实它是一个用VC7.1编译产生的动态链接库并且动态链接到MSVCR71.DLL。 由于HOOK函数需要把 IDLE.DLL 注入到所有的用户程序中,MSVCR71.DLL 也会被注入到所有的用户程序中。 而且这个IDLE.DLL 会进入所有用户程序的消息循环。在所有的程序中都有这个 idle.dll 实在是让人不爽。 ;)
Let's check the IDLE.DLL
下面就让我们看看这 IDLE.DLL
It has 3 C++ functions defined, and a customized data section "Y_IDLE", I think it is the shared data section which used to store the latest user active time stamp. While what's the function protocol for these 3 function? I found a very good documentation for the C++ name mangling of different compilers at URL http://www.agner.org/optimize/ Calling conventions for different C++ compilers and operating systems
它定义了三个输出函数,同时自定义了一个程序段 Y_IDLE 相比这应该是一个数据段,用来记录从各个应用程序收集到的最新的用户消息发出的时间。 而这三个函数应该是用C++的命名规则输出的,但是这三个函数的原型是什么呢?幸好发现了一个非常好的文档,详细地描述了各种编译器的 C++ name mangling 也就是符号标的转换规则。参见 http://www.agner.org/optimize/ Calling conventions for different C++ compilers and operating systems
In fact, from the Windows 2000, WIN_VER>=0x500 there is a new function GetLastInputInfo in user32.dll, it will provide the Last user input time stamp quickly.
其实从Window2000开始,微软在 User32.dll 就提供了一个新的函数 GetLastInputInfo 它就可以用来返回用户的最后输入的时间。
This will be able to create a new IDLE.DLL
这样就可以知道一个新的 idle.dll , 而且它也再也不会被注入到其他的程序中了。
替换原来的 IDLE.DLL 还真不错~~~~ 工作正常。
在找到 IDLE.DLL 输出函数的原型还真花了些时间。后来才发现其实微软已经给我们提供了一个很方便的工具,那就是随Platform SDK 分发的 Dependency Walker (depends.exe) 里面有一个 Undecorate C++ functions 的功能,我们只需要用Dependency Walker 打开 IDLE.DLL 就可以看到输出函数的原型了。
其实
Yahoo Messenger 是一个很不错的IM软件。但是它是用了一个非常陈旧的Windows Hook功能,因此制造了一个idle.dll 用来来检测用户的发呆时间。这个IDLE.DLL 文件看起来并不大,只有6k,其实它是一个用VC7.1编译产生的动态链接库并且动态链接到MSVCR71.DLL。 由于HOOK函数需要把 IDLE.DLL 注入到所有的用户程序中,MSVCR71.DLL 也会被注入到所有的用户程序中。 而且这个IDLE.DLL 会进入所有用户程序的消息循环。在所有的程序中都有这个 idle.dll 实在是让人不爽。 ;)
Let's check the IDLE.DLL
下面就让我们看看这 IDLE.DLL
C:\Program Files\Yahoo!\Messenger>dumpbin /exports idle.dll
Microsoft (R) COFF/PE Dumper Version 8.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file idle.dll
File Type: DLL
Section contains the following exports for idle.dll
00000000 characteristics
450867C8 time date stamp Thu Sep 14 04:19:20 2006
0.00 version
1 ordinal base
3 number of functions
3 number of names
ordinal hint RVA name
1 0 00001016 ?IdleUIGetLastInputTime@@YAKXZ
2 1 000010C3 ?IdleUIInit@@YAHXZ
3 2 0000111C ?IdleUITerm@@YAXXZ
Summary
1000 .data
1000 .rdata
1000 .reloc
1000 .rsrc
1000 .text
1000 Y_IDLE
It has 3 C++ functions defined, and a customized data section "Y_IDLE", I think it is the shared data section which used to store the latest user active time stamp. While what's the function protocol for these 3 function? I found a very good documentation for the C++ name mangling of different compilers at URL http://www.agner.org/optimize/ Calling conventions for different C++ compilers and operating systems
它定义了三个输出函数,同时自定义了一个程序段 Y_IDLE 相比这应该是一个数据段,用来记录从各个应用程序收集到的最新的用户消息发出的时间。 而这三个函数应该是用C++的命名规则输出的,但是这三个函数的原型是什么呢?幸好发现了一个非常好的文档,详细地描述了各种编译器的 C++ name mangling 也就是符号标的转换规则。参见 http://www.agner.org/optimize/ Calling conventions for different C++ compilers and operating systems
In fact, from the Windows 2000, WIN_VER>=0x500 there is a new function GetLastInputInfo in user32.dll, it will provide the Last user input time stamp quickly.
其实从Window2000开始,微软在 User32.dll 就提供了一个新的函数 GetLastInputInfo 它就可以用来返回用户的最后输入的时间。
/**
* This is used to hack the Yahoo Messenger.
* compiled with VC7.1 as:
* cl -W3 -O1sy -LD -MD -D_WIN32_WINNT=0x0500 idle.cpp -Feidle.dll User32.lib
*/
#include
#pragma section("Y_IDLE",read,write)
__declspec(allocate("Y_IDLE"))
int Y_IDLE = 0;
#define DllExport __declspec( dllexport )
DllExport DWORD IdleUIGetLastInputTime()
{
LASTINPUTINFO lii;
lii.cbSize = sizeof(lii);
GetLastInputInfo(&lii);
return lii.dwTime;
}
DllExport INT IdleUIInit()
{
return TRUE;
}
DllExport VOID IdleUITerm()
{
return;
}
This will be able to create a new IDLE.DLL
这样就可以知道一个新的 idle.dll , 而且它也再也不会被注入到其他的程序中了。
替换原来的 IDLE.DLL 还真不错~~~~ 工作正常。
写在后面
在找到 IDLE.DLL 输出函数的原型还真花了些时间。后来才发现其实微软已经给我们提供了一个很方便的工具,那就是随Platform SDK 分发的 Dependency Walker (depends.exe) 里面有一个 Undecorate C++ functions 的功能,我们只需要用Dependency Walker 打开 IDLE.DLL 就可以看到输出函数的原型了。
其实
订阅:
博文 (Atom)
BlockChain 相关电子书
@copyright of Sam Chadwick - https://thehub.thomsonreuters.com/groups/bitcoin/blog/2017/09/10/blockchain-paper Blockchain Papers A c...
-
为Windows 10 添加 拼音加加双拼 输入方案 把下面的内容保存为 ppp.reg, 然后双击导入注册表,Pinyin PlusPlus双拼输入方案就有了。 Windows Registry Editor Version 5.00 [HKEY_CURRENT...
-
算起来到这里已经一年多了, 中间断断续续当然了也包括一些可观的原因,一共也没有放多少东西上来。 总算还有两片篇幅较长的原创,也算是聊以自慰了。 再接再厉好了!希望自己能够百尺竿头更进一步~~~
-
Today I do update the JavaScript syntax script for VIM to 0.7.2. Until now PRC 2007.01.30-21:37 my script got: Rating 332/99, Downloaded by ...