如何在64位win10的VS2017环境下搭建汇编环境

用户AcmeContracted安装masm32失败,所以想知道是否能集成masm64到Visual Studio 2017中

VS里面masm不是单独的,是C++工具集的一部分,而在VS2017里C++工具集不是默认安装的,所以要先安装C++工具集。

安装完之后创建个C++的Win32命令项目,然后在解决方案浏览器里选中项目节点,右键,选择Build Dependencies->Build Customisations,在弹出的对话框里选中masm,然后选择OK。这会使得你的项目里的新asm文件使用ml或者ml64编译(具体使用哪个取决于你的项目当前编译配置是32位还是64位)。

另外VS里面新建文件的选择里没有asm文件的模板,随便选个纯文本格式(.h,cpp,.txt,.html都行)的来替代,建完了把扩展名改成asm,然后在解决方案浏览器里右键点文件打开文件属性对话框,把项目类型改成Microsoft Macro Assembler。确定之后这个文件就会用masm来编译了,可以重新打开文件属性对话框检查编译时使用的命令行。

如果的项目在启用asm支持之前已经有了asm文件,这些asm文件的编译设置不会被VS2017版的覆盖(因为有可能在使用第三方的asm)。如果没有值得保留的旧编译设置,可以在解决方案浏览器里右键点文件,选择排除(注意不是删除),再把文件加回来。

Advertisements
Posted in Uncategorized | Leave a comment

Can we run 32 bit and 64 bit code in the same process?

User redstone001 wants to know if it is possible to run 32 bit and 64 bit code in the same process – maybe in a different thread?

As Betteridge’s law of headlines say, any news ending with a question mark can be answered with the word no. But this isn’t news, so … the answer is … yeah? Kind of.

The way that Windows implements a 32 bit emulator (e.g. making  Program Files (x86) appear as Program Files to 32 bit processes) is to load 64 bit system dlls in 32 bit code… but specially crafted 64 bit dlls indeed. To be callable from a 32 bit process, everything they generate have to be 32 bit compatible. E.g. do not provide access outside of the x86 memory address space, and zero out higher 32 bit of handles etc. The way it is written is practically creating 64 bit dlls that enjoy none of the 64 bit benefits, but become much slower and heavier thanks to marshal 32 bit calls to 64 bit before calling other system dlls. Because there is no up side except compatibility, Windows only allows its own 64 bit DLLs to be callable inside a 32 bit process. If you want to reuse your code written for a different CPU architecture, it would be much faster to run a separate process and do interprocess communication.

Posted in Computers and Internet | Leave a comment

Farewell, dsoframer

I know, it is long overdue. Microsoft discontinued it a decade ago. And Office is not meant to be embedded. I even advised people to not use it in new development almost a decade ago. Then why I keep using it for so long?

Because customers don’t want changes. I work in the medical field, where some of the clients still use telnet to interface with their medical software that are probably older than I am. Once you get people hooked to a UI it is hard to change that. The fact that Microsoft discontinues dsoframer means nothing to them – once I use it, I own it. It is like Microsoft having to release an Office update for the old equation editor made by MathType 16 years ago. So I have been doing patchwork as much as I can to keep dsoframer alive.

It might be a blessing in disguise that Office 2016 finally broke dsoframer on Windows 10 in a way that I can’t fix. The control just keep calculates the scrolling sizes wrong. I have to work on a solution for customers who can accept a side-by-side UI instead of embedding Office. Shortly after I published the update Microsoft dropped the bomb that the MSI edition of Office is being discontinued, I have to say that I am lucky to have some doctors finally start accepting the side by side UI. Maybe the rest will also get use to it now there’s no alternative.

Some issues I encountered over the years

The click-to-run edition of Office dropped the registry entries required by dsoframer to function .

.Net Programmability support is not a default install option of Office

Adobe Acrobat Reader shipped with dsoframer too, and uninstall either the reader or my app breaks the remaining one. Note to self: GuidGen on samples.

Does not open document if Office is running

Various drawing issues.

I supported embedding Word longer than the Outlook team, I am really not proud of that.

Posted in Microsoft | Tagged , | 2 Comments

Getting around “Strong name signature not valid for assembly” for a ClickOnce application

When building a ClickOnce application, I need to redistribute a third party dll. But it failed the strong name validation under sn-vf thus ClickOnce launcher failed with the same error.

Microsoft (R) .NET Framework Strong Name Utility Version 4.0.30319.0
Copyright (c) Microsoft Corporation. All rights reserved.

Failed to verify assembly — Strong name validation failed.

I have no idea why the vendor signed a the file with the correct Authenticode signature but with the wrong strong name signature . However, given that they never released an update, it is unlikely to have them to fix the problem on their end.

Based on my research I now have three options:

  1. remove the strong name signature, find and replace all references to this dll by ildasm and modifying the result il code to remove the PublicKeyToken from the reference, then recompile the il code to dll using ilasm
  2. bypass ClickOnce’s strong name signature validation by coding
  3. sn-vr to remove the file from strong name signature validation

Because the dll is referenced by too many other third party assemblies it is kinda time consuming to modify all of them. And I don’t really have the permission to run anything else but my ClickOnce app on client machines so changing client side strong validation name policy is out too. I continued with the second route.

First thing I tried was to rename the file. After all, ClickOnce did not complain my database file’s strong name signature right? So I went ahead and set the reference’s CopyLocal property to false, excluded the file from application files, and added a copy of the dll under the name of dllname.dll1 to the project.  With the BuildAction property set to content this would add the dll1 file as a data file .  At the run time I used the AssemblyResolve event to load the dll1 file as an assembly when the dll is requested. Debugged the AssemblyResolve  code so the program ran without a dllname.dll file in the application directory. Now publish it as a ClickOnce Application and wait…

And ClickOnce launcher reported the same error! So ClickOnce validates strong name for data files as long as it has one, regardless of the file extension. Maybe I need to hide the strong name somehow. A natural wrapper would be a zip file, I can unzipping the file for use during AssemblyResolve .Unzipping during AssemblyResolve did not really work, the dll loading failed when I called SharpZipLib to extract the zip file. So this looked like a catch 22 – AssemblyResolve fails when loading another dll and I need another dll to unzip the file (or I have to ilmerge the code to my main executable, another thing I don’t want to do).

So AssemblyResolve is out of question. I have to unzip the dependency files before use. A natural time to do this is the beginning of Program.Main. And ClickOnce has no problem with my zip file approach now.

Since I got this zip mechanism in place what I can do more about it? Maybe putting other files that I do not really update in the file like my UI framework library or Microsoft Enterprise Library? But then I get dll not found exception before Main is executed. Maybe I need to move the extraction even earlier. What gets executed before Main? Static constructors! After moving the extracting code to a static constructor, I now suddenly cut my download size from 100mb to 30mb, a nice bonus indeed.

Posted in C#, enmsdn, Microsoft | Tagged | Leave a comment

What part of Windows is written in .Net/WPF/Silverlight?

user 曹一聪 on zhihu is curious how widely .Net is used within Windows components.

Obviously an operating system component cannot depend on something that isn’t in the operating system, so nothing uses Silverlight in the desktop version Windows. And because XP editions mostly did not ship with any .Net framework version, practically nothing from the XP days can use .Net. Only components newer than XP or rewrote after XP can use .Net, except those Windows Media Center and Tablet PC components that have .Net dependencies.

The first time .Net is available in almost all editions is Windows Vista/2008 (the server core editions make .Net optional). Because a Vista Capable sticker does not guarantee a machine with user-acceptable speed, not much in Windows Vista is using .Net. OR Windows 7 on that matter if you skip Windows Powershell. The usage of .Net is more in the consumer software (e.g. Windows Live Essentials), developer tools (e.g. Visual Studio) and business tools (e.g. SQL Server). In short, .Net is for writing apps, not really for the OS itself.

After Windows 8, Microsoft’s focus moved to Windows RT, now UWP, not much effort is done to improve the desktop, so practically nothing in the desktop got rewritten in .Net Framework.  Windows Help 2.0 is a notable exception however. Because more and more desktop components are moving to UWP (control panel, calculator, games etc), Windows 8 might be the peak of .Net Framework usage in Windows.

If you want a completed list of managed assemblies, you can just scan all dll/exe files on your system and see which file is a managed. And if a file is a managed assembly, search its references to find if WPF is used. AssemblyName.GetAssemblyName can detect a managed assembly file but it throws too many exceptions as most dll/exe files are not managed, so I use Meta Data APIs (IMetaDataDispenser/IMetaDataImport) to detect managed assemblies. The full code can be found at github.com/jiangsheng/Samples/blob/master/FindDotnetInWindows.

The initial list of managed files I found is pretty long so the scanner skip known locations that have known .Net assemblies, like the GAC, the .Net Framework folder, Windows Powershell, Visual Studio, SQL Server and  IIS. The usage of .Net in the rest of system is surprisingly sparse.  Windows itself is still a C/C++ stronghold.

Posted in enmsdn, Microsoft | Tagged , | 1 Comment

Flash Player: Loading from memory

user cucao wants to know how to play a flash file from application resource. The user wants to use a dongle to protect unauthorized viewing of the flash file so can’t just put the swf file in plain sight.

Adobe’s Flash Player, being an ActiveX with supports for many OLE containers such as Internet Explorer and Microsoft Word, implements many standard OLE interfaces (for details open the ActiveX in oleview). One of them is IPersistStreamInit, a standard interface for ActiveX controls who want to distinguish new page load vs refresh, but can be used for the user to load the swf file from memory.

The data source passed into IPersistStreamInit::Load could be a home-brew COM server that implements IStream, but since Windows already has such an implementation (CreateStreamOnHGlobal), it saves a lot of work to just load the resource into global memory (GlobalAlloc/GlobalLock/memcpy/GlobalUnlock), and creates a stream off there for loading.

//MFC and ATL instead of Windows API for readability

void LoadFlash(LPUNKNOWN player, LPCVOID data, UINT size) {
COleStreamFile streamFile; if(!streamFile.CreateMemoryStream() return;
CArchive ar (&streamFile, CArchive::store );
ar.Write(data,size); ar.Close();
streamFile.SeekToBegin();
CComQIPtr<IPersistStreamInit> playerStreamLoader(player);
if(playerStreamLoader==NULL) return;
playerStreamLoader->InitNew();
playerStreamLoader->Load(streamFile.GetStream());
}

This only works for self-contained swf files, however. To set a base url for relative url search in action scripts, a home-brew COM server that implements both IStream and IMoniker is needed.

Posted in ATL, enmsdn, MFC, Microsoft Foundation Class Library | Tagged , , , | Leave a comment

What’s new in Visual Studio Tools for Windows 10 Preview

Looks like Windows 10 SDK gets renamed.

This post focuses on the Win32 wide of changes. Changes in the WinRT Universal App Platform (UAP) side can be found at https://dev.windows.com/en-us/whats-new-windows-10-dev-preview. Some UAP APIs are available to all desktop apps, for exam DirectX 12 and notification center (should not come as surprise, older version of these APIs are already callable from Win32 apps ). Project Centennial also supports enabling UAP APIs to desktop apps, provided they meet certain requirements and deploy using the new appx model.

In

DirectX12 (of course)

The Spartan webbrowser (not sure, some Spartan-specific commands like IDM_SHAREPICTURE exists but no word on how to host a Spartan webbrowser)

new API partition WINAPI_FAMILY_ONECORE_APP

Support for ARM 64

Universal CRT 

Windows Core Audio improvements: Prioritize buffer selection in Windows Core Audio APIs to reduce audio latency (e.g. alerts, game effects, game chats, user speech, movie etc) . Low power consumption audio is there for WinRT but not for Win32 :(. Well DJs are gonna be happy about this change.

Unsurprisingly some low power API for video codec too. Guess playing movies do kill battery life.

Losts of changes in the Certificate Enrollment API…. and what’s up with the desktop family guard macros? someone gonna try include the headers in a Windows Store app?

APIs for not domain/AD joined clusters. Wow the documentation is up in MSDN already. The Windows Server team is faster this time. Guess the consumer team fall behind because of the Phone edition.

Wow Microsoft is adding stuff to COM again. Did not expect this to happen. The REGCLS enumeration gets a new member.. after 15 years.

You are joking right? Why this empty ifdef in the tree control styles and extended styles? Looks like something got cut.

#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
#endif

API for Jet – Extensible Storage Engine version version 10, like the new 8-byte unsigned long long column type.

IShellUIHelper7 adds some more methods to the window.external object… like SelectUAString and getter/setter methods for experimental flag. Can I change between Trident and EdgeHtml this way?

Secured D3D in Media Foundation. Guess WebGL forced that.

Now you can customize the context menu in a PDF document displayed in a hosted webbrowser control.

Some new SQLite-specific error codes in winerr.h. It seems SQLite is part of OS.

New system folders like camera roll and saved pictures. FOLDERID_SkyDrive is getting renamed (of course) but will remain for some time for backward compatible reasons.

TODO: neerajsi-2013/12/08 – this should be moved to official documentation.huh?

Graphics streaming in Remote Desktop APIs.

Out:

D3D 8 (it is still there in Windows 8? Did not notice)

IA64

Moved (desktop APIs that were not available to Windows Store apps to be supported in universal apps)

Threading (CreateThread etc)

Winsock

Posted in enmsdn, Microsoft | Tagged , | Leave a comment

Book review: Mastering Windows 8 C++ App Development

Disclaimer: I am a Microsoft MVP in Visual C++, so is Pavel Yosifovich, the author of the book.

Mastering Windows 8 C++ App Development by Pavel Yosifovich is a new addition to the Windows Store development books. It took me a while to read (304 pages) but is well worth the time from the perspective of a C++ developer.

The book obviously went through great lengths to be comprehensive, not only introduced the typical Windows Runtime (WinRT) APIs in a crisp manner but also added a refreshment of C++ 11, the Model View ViewModel (MVVM) pattern, and the Windows Runtime C++ Template Library (WRL). In addition, being a book for C++ developers, the author’s emphasis on performance can be found in several tips and discussions, which is a nice focus for C++ developers.

There are also several weaknesses in the book. Introducing WRL before C++/CX may be a poor choice as it is difficult to inspire the reader with laborious code. Also the book could use a few more details on DirectX and some WinRT APIs such as GeoPosition.

Nevertheless, the book is an excellent text for the subject and I recommend the book to C++ programmers who want to start developing Windows Store apps and can do research outside of the book.

Posted in enmsdn, Microsoft, Visual C++, Visual Studio | Tagged , , , , , , | Leave a comment

Another breaking change related to 64 bit compatibility, this time in TAPISRV w/Windows 8

The ADO team had to make a breaking change the ADO APIs due to compatibility problem with Microsoft Office. Now it seems to be Tapi’s turn. In the 64 bit editions of Windows 8 and Windows Server 2012, some TAPI providers would stop getting incoming calls due to implementation changes in the TAPI service (TAPISRV) that had to be done for 64 bit compatibility.

The problem is pretty obvious from the documentation, for example LINE_NEWCALL has this:

htLine = (HTAPILINE) hLineDevice;
htCall = (HTAPICALL) 0;
dwMsg = (DWORD) LINE_NEWCALL;
dwParam1 = (DWORD)(HDRVCALL) hdCall;
dwParam2 = (DWORD)(LPHTAPICALL) &htCall;
dwParam3 = (DWORD) 0;

The parameters can’t really be passed as DWORDs – on a 64 bit build, pointers are 64 bit in size, and a DWORD is 32 bit.

Fortunately this can be corrected fairly easily, just ignore what the documentation said and treat the DWORD parameters as DWORD_PTR, however for the end users they would need updates from TAPI providers to get TAPI working on their Windows 8 /Server 2012 machine.

According to TAPI MVP Andreas Marschall, the following TAPI providers are affected (If you got a provider released before 2012,  it is likely also affected)

  • Avaya TAPI
  • Acatel-Lucent TSP
  • NEC TSP (for PBX NEC SL1100)
  • Siemens HiPath TAPI 120/170 (V2 R1.66.0)
Posted in enmsdn, Microsoft | 1 Comment

Howto: Ignoring web browser certificate errors in a webbrowser host

The webbrowser queries host services via IServiceProvider implemented on the ActiveX host. One of the services is IHttpSecurity, which can be used to override the certificate problem dialog.

Security warning: ignoring security problems can compromise your application.

IHttpSecurity is derived from IWindowForBindingUI, so the host needs to implement it too.

In Windows forms, customizing certificate error handling involves the following:

  • derive a class from WebBrowser
  • create a nested class derived from WebBrowser.WebBrowserSite (the only way you can derive from the nested class)
  • overwrite CreateWebBrowserSiteBase and return a new instance of your webbrowser site.
  • implement IServiceProvider on the webbrowser site
  • implement IServiceProvider.QueryService so it returns an IHttpSecurity imepleemntation when the IHttpSecurity service is requested
  • handle IHttpSecurity.OnSecurityProblem and return S_OK (warning: undocumented code, won’t work in IE6)
  • use the new webbrowser in the form

Sample code:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void webBrowser1_DocumentCompleted(object sender,
            WebBrowserDocumentCompletedEventArgs e)
        {
            if (e.Url.ToString() == “about:blank”)
            {
                //create a certificate mismatch
                webBrowser1.Navigate(“https://74.125.225.229&#8221;);
            }
        }
    }
    [Guid(“6D5140C1-7436-11CE-8034-00AA006009FA”)]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [ComImport]
    public interface UCOMIServiceProvider
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int QueryService(
            [In] ref Guid guidService,
            [In] ref Guid riid,
            [Out] out IntPtr ppvObject);
    }
    [ComImport()]
    [ComVisible(true)]
    [Guid(“79eac9d5-bafa-11ce-8c82-00aa004ba90b”)]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IWindowForBindingUI
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int GetWindow(
            [In] ref Guid rguidReason,
            [In, Out] ref IntPtr phwnd);
    }
    [ComImport()]
    [ComVisible(true)]
    [Guid(“79eac9d7-bafa-11ce-8c82-00aa004ba90b”)]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IHttpSecurity
    {
        //derived from IWindowForBindingUI
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int GetWindow(
            [In] ref Guid rguidReason,
            [In, Out] ref IntPtr phwnd);
        [PreserveSig]
        int OnSecurityProblem(
            [In, MarshalAs(UnmanagedType.U4)] uint dwProblem);
    }
    public class MyWebBrowser : WebBrowser
    {
        public static Guid IID_IHttpSecurity
            = new Guid(“79eac9d7-bafa-11ce-8c82-00aa004ba90b”);
        public static Guid IID_IWindowForBindingUI
            = new Guid(“79eac9d5-bafa-11ce-8c82-00aa004ba90b”);
        public const int S_OK = 0;
        public const int S_FALSE = 1;
        public const int E_NOINTERFACE = unchecked((int)0x80004002);
        public const int RPC_E_RETRY = unchecked((int)0x80010109);
        protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
        {
            return new MyWebBrowserSite(this);
        }
        class MyWebBrowserSite : WebBrowserSite,
            UCOMIServiceProvider,
            IHttpSecurity,
            IWindowForBindingUI
        {
            private MyWebBrowser myWebBrowser;
            public MyWebBrowserSite(MyWebBrowser myWebBrowser)
                :base(myWebBrowser)
            {
                this.myWebBrowser = myWebBrowser;
            }
            public int QueryService(ref Guid guidService
                , ref Guid riid
                , out IntPtr ppvObject)
            {
                if (riid ==IID_IHttpSecurity)
                {
                    ppvObject= Marshal.GetComInterfaceForObject(this
                        , typeof(IHttpSecurity));
                    return S_OK;
                }
                if (riid == IID_IWindowForBindingUI)
                {
                    ppvObject = Marshal.GetComInterfaceForObject(this
                        , typeof(IWindowForBindingUI));
                    return S_OK;
                }
                ppvObject = IntPtr.Zero;
                return E_NOINTERFACE;
            }
            public int GetWindow(ref Guid rguidReason
                , ref IntPtr phwnd)
            {
                if (rguidReason == IID_IHttpSecurity
                    || rguidReason == IID_IWindowForBindingUI)
                {
                    phwnd = myWebBrowser.Handle;
                    return S_OK;
                }
                else
                {
                    phwnd = IntPtr.Zero;
                    return S_FALSE;
                }
            }
            public int OnSecurityProblem(uint dwProblem)
            {
                //ignore errors
                //undocumented return code, does not work on IE6
                return S_OK;
            }
        }
    }
For sample code in providing the service using MFC, check Handle NewWindow3 and ShowModalDialog in CHtmlView. The way to implements IHttpSecurity is similar to how the article exposes the INewWindowManager service to the webbrowser control.
Posted in C#, MFC, Microsoft, Visual Studio, Webbrowser control | Tagged , , , , , | 15 Comments