3/22/2010

DirectUI和无窗口用户界面

DirectUI/DirectUser是一个用户界面框架(http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.automationelementinformation.frameworkid.aspx)。用Spy++可以在MSN Messenger、Windows XP、Office、IE和Windows Media Player中看到窗口类名字是DirectUIHWND的窗口。

从文件描述来看,DUI70.dll和DUser.dll看起来是这个框架的实现文件,而没有导入这些DLL的软件应该是复制了这个库的代码。举例来说,Windows Vista和IE7的测试版的IEFrame.dll导入了DUser.dll(http://social.msdn.microsoft.com/Forums/en-US/windowsuidevelopment/thread/6b801577-1699-4093-8a58-198c64b120e0)而正式版使用IEUI.DLL。这应该是微软不愿意公开支持这个功能变化频繁的类库,而反垄断案禁止非Windows组件调用未公开Windows API的缘故。

再看看DUser.dll的函数导出表(http://www.webtropy.com/articles/dll-api.aspx?dll=duser),可以看到Gadget这个词被广泛使用,而没有具体的控件。因为没有窗口句柄,所以控件不会是用的窗口类来区分,而是可能和Windows Vista Sidebar Gadgets一样采用HTML做接口(更正)从Office Communicator的资源来看,是用的XML做的接口。。

从这个类库的名字和行为来看,实际上应该是基于DirectX,和WPF类似的界面类库框架。在微软的招聘网站上可以看到Office Communications项目组的一个职位的介绍中描述说“Native Win32/64 UX experience via DirectUI, and Web UX experience via Silverlight”,说明这个项目组把它和Silverlight同等对待。DirectUIHWND窗口可以在需要性能和安全性的场合看到,例如IE的Tab窗口、Shell中的DefView、Windows登录界面等等。在Windows Vista上使用DirectUI的微软程序和WPF程序一样兼容Desktop Composition和远程桌面,应该是直接或者间接调用的Direct3D。

那么我们怎么做到类似的效果?

无窗口模式的用户界面并不是一个新的概念(http://blogs.msdn.com/oldnewthing/archive/2005/02/11/371042.aspx),VC的应用程序向导就可以创建无窗口ActiveX。但是做过无窗口模式的RichEdit的实现的人都知道,微软的系统控件集中了各种各样的功能,比如各种快捷键、滚动条、界面风格、Accessibility、用户界面自动化等等,要像IE项目组那样几乎完全实现无窗口并不容易。Raymond Chen在(http://blogs.msdn.com/oldnewthing/archive/2005/02/11/371042.aspx)提到可以使用DrawThemeBackground和DrawFrameControl这两个API,不过这只对和Windows界面风格一致的程序有用。要是界面不复杂的话,可以简单的集成IE的Trident引擎,比如使用MFC的CHTMLView和CDHTMLDialog,以及Windows Forms的WebBrowser类。这样做的代价就是程序需要牺牲性能和可能在严格的IE安全性配置下无法工作,Visual Studio.Net开始的各种向导、Google Task、Microsoft Outlook、Outlook Express等就是使用的这种方案。

另外一个方案就是集成WPF或者Silverlight。VC项目组在用户调查中发现,需要使用WPF的Visual C++用户大都用C#编写WPF代码再用C++/CLI和非托管代码做接口(http://social.msdn.microsoft.com/forums/en-US/wpf/thread/dd1e31bb-feb4-4d77-b524-42a282f519b1/),所以他们决定致力于改进更多用户使用的功能,例如编辑器的智能感知,而不提供对WPF的支持。Visual Studio 2010就是使用这种方案。

为什么不能使用未公开的API?参考

http://blogs.msdn.com/oldnewthing/archive/2003/12/23/45481.aspxhttp://blogs.technet.com/stefan_gossner/archive/2005/07/27/undocumented_API_Part1.aspx

题后话:

*如果微软在产品文档中讨论未公开的API,那么API还是未公开的吗?(http://msdn.microsoft.com/en-us/library/aa140182(office.10).aspx)

*Visual Studio代码画廊中有个叫作DirectUI的类库,设计思想和微软的DirectUser库类似(http://visualstudiogallery.msdn.microsoft.com/en-us/1B69C9FE-E422-4799-9EB5-6AC7034C52E1),不过也有人误认为这就是微软用来实现MSN的界面的库。

*IE9将会使用Dierct2D作为渲染引擎,不知道IE项目组在移植完代码之后是否能把控件类库的接口公开

DirectUI/DirectUser是一个用户界面框架(http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.automationelementinformation.frameworkid.aspx)。用Spy++可以在MSN Messenger、Windows XP、Office、IE和Windows Media Player中看到窗口类名字是DirectUIHWND的窗口。

从文件描述来看,DUI70.dll和DUser.dll看起来是这个框架的实现文件,而没有导入这些DLL的软件应该是复制了这个库的代码。举例来说,Windows Vista和IE7的测试版的IEFrame.dll导入了DUser.dll(http://social.msdn.microsoft.com/Forums/en-US/windowsuidevelopment/thread/6b801577-1699-4093-8a58-198c64b120e0)而正式版使用IEUI.DLL。这应该是微软不愿意公开支持这个功能变化频繁的类库,而反垄断案禁止非Windows组件调用未公开Windows API的缘故。

再看看DUser.dll的函数导出表(http://www.webtropy.com/articles/dll-api.aspx?dll=duser),可以看到Gadget这个词被广泛使用,而没有具体的控件。因为没有窗口句柄,所以控件不会是用的窗口类来区分,而是可能和Windows Vista Sidebar Gadgets一样采用HTML做接口。

从这个类库的名字和行为来看,实际上应该是基于DirectX,和WPF类似的界面类库框架。在微软的招聘网站上可以看到Office Communications项目组的一个职位的介绍中描述说“Native Win32/64 UX experience via DirectUI, and Web UX experience via Silverlight”,说明这个项目组把它和Silverlight同等对待。DirectUIHWND窗口可以在需要性能和安全性的场合看到,例如IE的Tab窗口、Shell中的DefView、Windows登录界面等等。在Windows Vista上使用DirectUI的微软程序和WPF程序一样兼容Desktop Composition和远程桌面,应该是直接或者间接调用的Direct3D。

那么我们怎么做到类似的效果?

无窗口模式的用户界面并不是一个新的概念(http://blogs.msdn.com/oldnewthing/archive/2005/02/11/371042.aspx),Visual C++的应用程序向导就可以创建无窗口ActiveX。但是做过无窗口模式的RichEdit的实现的人都知道,微软的系统控件集中了各种各样的功能,比如各种快捷键、滚动条、界面风格、Accessibility、用户界面自动化等等,要像IE项目组那样几乎完全实现无窗口并不容易。Raymond Chen在http://blogs.msdn.com/oldnewthing/archive/2005/02/11/371042.aspx提到可以使用DrawThemeBackground和DrawFrameControl这两个API,不过这只对和Windows界面风格一致的程序有用。要是界面不复杂的话,可以简单的集成IE的Trident引擎,比如使用MFC的CHTMLView和CDHTMLDialog,以及Windows Forms的WebBrowser类。这样做的代价就是程序需要牺牲性能和可能在严格的IE安全性配置下无法工作,Visual Studio.Net开始的各种向导、Google Task、Microsoft Outlook、Outlook Express等就是使用的这种方案。

另外一个方案就是集成WPF或者Silverlight。VC项目组在用户调查中发现,需要使用WPF的Visual C++用户大都用C#编写WPF代码再用C++/CLI和非托管代码做接口(http://social.msdn.microsoft.com/forums/en-US/wpf/thread/dd1e31bb-feb4-4d77-b524-42a282f519b1/),所以他们决定致力于改进更多用户使用的功能,例如编辑器的智能感知,而不提供对WPF的支持。Visual Studio 2010就是使用这种方案。

为什么不能使用未公开的API?如果要看惊恐故事的话,可以参考http://blogs.msdn.com/oldnewthing/archive/2003/12/23/45481.aspxhttp://blogs.technet.com/stefan_gossner/archive/2005/07/27/undocumented_API_Part1.aspx

题后话:

*如果微软在产品文档中讨论未公开的API,那么API还是未公开的吗?(http://msdn.microsoft.com/en-us/library/aa140182(office.10).aspx

*Visual Studio代码画廊中有个叫作DirectUI的类库,设计思想和微软的DirectUser库类似(http://visualstudiogallery.msdn.microsoft.com/en-us/1B69C9FE-E422-4799-9EB5-6AC7034C52E1),不过也有人误认为这就是微软用来实现MSN的界面的库。

*IE9将会使用Dierct2D作为渲染引擎,不知道IE项目组在移植完代码之后是否能把控件类库的接口公开

3/04/2010

Getting out of Active Document

do{
            if(m_pDocObjectServer==NULL) break;
            CComPtr<IOleObject> pOleObject;
            m_pDocObjectServer->ExternalQueryInterface(&IID_IOleObject,(LPVOID*)&pOleObject);
            if(pOleObject==NULL) break;
            CComPtr<IOleClientSite> pOleClientSite;
            pOleObject->GetClientSite(&pOleClientSite);
            if(pOleClientSite==NULL) break;
            CComPtr<IOleContainer> pOleContainer;
            pOleClientSite->GetContainer(&pOleContainer);
            if(pOleContainer==NULL) break;
            CComQIPtr<IServiceProvider> pServiceProvider(pOleContainer);
            if(pServiceProvider==NULL) break;
            CComQIPtr<IServiceProvider> pTopLevelServiceProvider;
            pServiceProvider->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (LPVOID*)&pTopLevelServiceProvider);
            if(pTopLevelServiceProvider==NULL) break;
            CComPtr<IWebBrowser2> pWebBrowser2;
            pTopLevelServiceProvider->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2,(LPVOID*)&pWebBrowser2);
            if(pWebBrowser2==NULL) break;           
            pServiceProvider=pWebBrowser2;
            CComPtr<IOleWindow> pOleWindow;
            pServiceProvider->QueryService(SID_SShellBrowser, IID_IOleWindow,(LPVOID*)&pOleWindow);
            if(pOleWindow==NULL) break;           
            HWND hwndBrowserOrTab = NULL;
            pOleWindow->GetWindow(&hwndBrowserOrTab);
            if(hwndBrowserOrTab==NULL) break;           
            CString newTitle;
            newTitle.Format("%s (%d strokes)",
                m_strPathName,
                m_strokeList.GetSize());
            BOOL result=::SetWindowText(hwndBrowserOrTab,(LPCTSTR)newTitle);
            if(result==FALSE)
            {
                int errorCode=GetLastError(); //no error here but looks like no way to update tab caption, which is in a DirectUIHWND window in the frame process.
            }
        }while(FALSE);

11/10/2009

Class Wizard is back to Visual C++ in Visual Studio 2010... Control Shift X.

image

After 4 versions. Finally.

More features: Now you have partial search in options

The Wizard does not always find every handler function.  I got warning when trying to create a handler if there is one already. Delete handler does not work when an existing handler is not detected.

Sometimes I have “value does not fall in expected range” when trying to bring the class wizard if I have source files open.

8/27/2009

关于最近Visual Studio的ATL更新

如果使用Visual C++ 2005或者2008,那么这个更新可能已经被自动安装了。这个更新修补了ATl库中的一些安全问题。在安装这个更新之后,Visual C++运行时刻库会升级。这意味着如果代码面向的CRT版本是_CRT_ASSEMBLY_VERSION或者_BIND_TO_CURRENT_VCLIBS_VERSION,那么要随着新编译的程序发布新版本的CRT。如果程序没有定义这些宏,那么安全更新安装的重定向策略会把绑定到旧版本的引用自动转向新的CRT版本。

一个常见的问题是链接到旧版本的编译器生成的库文件。这样会在编译器生成的应用程序清单中生成两个不同版本的CRT引用。这时候要用合并模块或者手动编辑策略文件,确保重定向策略被正确安装到系统。

由于用户未必安装了Windows Update补丁,程序员需要随程序发布最新的Visual C++文件。对于vcredist发布的程序,可以直接下载Microsoft Visual C++ 2005 Service Pack 1 Redistributable Package ATL Security Update。这个再发布包也可以在安装了Visual Studio的计算机中找到。对于使用安装程序制作工具的场合,Visual Studio会更新安装和部署项目使用的合并模块(Program Files\Common Files\Merge Modules)和bootstrapper(Program Files\Microsoft SDKs\Windows\版本号\Bootstrapper\Packages或者Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages),第三方安装程序制作软件则可能需要安装补丁或者手动替换Visual C++文件。如果应用程序把VC文件发布到安装文件夹,那么安装文件夹内的文件也需要更新以使用最新的运行时刻库和版本重定向策略。

一些旧版本的Windows SDK也包含ATL,建议使用新版本的ATL以避免安全问题。如果在安装了Visual Studio 2008 SP1之后安装了Windows SDK 6.1,那么在编译ATL项目时会出现编译错误

error C2039: '_Swap_adl' : is not a member of 'std' c:\program files\microsoft visual studio 9.0\vc\include\xutility 2764
error C3861: '_Swap_adl': identifier not found c:\program files\microsoft visual studio 9.0\vc\include\xutility 2764

这是由于Windows SDK 6.1包含Visual Studio 2008版本的ATL。解决办法是卸载SDK和VisualStudio,先装SDK,后装Visual Studio、SP1和ATL更新。

这个更新包含的不只是ATL的头文件,可以在KB971092里面看到大堆的PDB和再发布文件也被更新了。不建议手动更改ATL头文件来绕过安全问题,这样的话微软的更新程序不能更新修改过的文件。如果你已经手动更改了ATL的头文件,可以重新运行VisualStudio安装程序,卸载VisualC++之后重新安装,再应用SP1和ATL更新。下次修改系统头文件的时候,可以把文件复制到自己的目录,修改之后更改Visual C++的目录搜索路径。

关于这个更新的更多信息,可以参考MSDN第9频道的视频

5/31/2009

Bug in Media Player causes shutdown of Internet in China.

China’s Internet Service Providers (ISPs) do not like to talk to each other. the vast majority (90% in 2006) of customer complains received by the Ministry of Information Industry is about super slow interconnectivity of the two major ISPs, China Telecom and China Netcom, and people’s workarounds of the interconnectivity problem have side effects, like the recent Internet outrage caused by the Baofeng Media Player.

Here is a little background. The interconnectivity problem arose after the spin-off of China Netcom from China Telecom 2002. Before the split, China Telecom had a monopoly on network bandwidth, and local ISPs could not really compete with China Telecom because they had to rent China Telecom’s bandwidth for non-local services. The government ordered a split of the company after most of local ISPs went out of business, and created the interconnectivity problem.

After the spin-off, the China Telecom network is now split into two subnets, China Telecom in south and China Netcom in north. The two companies employed some anticompetitive tactics, including exclusive service agreements with estate developers and not keeping up with growing demand of interconnectivity between major networks. In 2006, the only bridge between them was a connection point at Beijing, which was often so overwhelmed that it was usually slower than routing though a USA network or switching to China Mobile’s CDMA wireless network.

In fact, the majority of connectivity was done by businesses. With ISPs reluctant to connect each other themselves, the only solution was to connect both networks and double the connectivity expense. At the beginning, the users were directed to ISP-specific addresses like http://chinatelecom.example.com in the China Telecom network, and http://chinanetcom.example.com in the China Netcom network. The problem was, users often didn’t know what their ISP is when they are not visiting Internet at home. Soon ISP-specific domain name service (DNS) server were created to direct visitor to the the address inside the visitor’s network. Now the user can use http://www.example .com and the DNS will decide which address the user will be visiting based on the user’s network. The free, personal financed DNSPod is this kind of DNS service.

Unfortunately, several DNS servers of DNSPod were hit by a distributed denial-of-service (DDOS) attack on the night of May 18. DNSPod’s owner did not think the attack was serious, because he dealt with larger attacks before. However, the DNS server China Telecom shut-off this time was hosting a web site used by the Baofeng Media Player, which manifested the DNS outrage to a much greater magnitude.

There was no explanation why the Baofeng Media Player’s company, a multi-million dollar investment with a self-claimed user base of 200 million , is using a free (*read* no warranty of any kind, agreed not liable to damage before using) DNS service. However, the greater mistake was that the Baofeng Media Player’s advertisement downloading service was programmed to go through each server on its server list until it gets an answer. When the ISP’s local DNS cache pointing to the downed DNSPod server expired, the requests to find servers put almost all DNS servers in China under a DDOS attack . At the attack’s peak, Baofeng Media Player’s DNS requests occupied 40% of China Telecom’s total bandwidth. A DDOS attack targeting a specific domain now transformed into a DDOS attach on almost all DNS servers in China, which slowed down the Internet in China to a crawl.

After a day of network outrage, there are lessons to be learned , from programming errors to doubtful business tactics. One thing is for sure, Baofeng Media Player’s advertisement downloading service is the one to blame for this disaster. However, Baofeng Media Player is not the first software with bugs, nor will it be the last one. China ISPs need to think about how to avoid this problem in the future, the sooner the better.