воскресенье, 10 февраля 2013 г.

MFC in desktop Windows RT apps

As we can build desktop Windows RT applications now - it is a good idea to use MFC for GUI. But suddenly I've found that there is no MFC 11.0 for ARM in Visual Studio 2012, even with the ARM WDK installed! The program compiles fine as the headers are present, but you'll get linker errors stating that uafxcw.lib, uafxcwd.lib and similar files are not found. Only ATL is present for ARM.
The first thought was to use dll2lib to generate import library from a mfc110.dll, but that DLL exports functions only by ordinals. So I've decided to look for mfc*.def in the "Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\src" dir and was surprised not to find it there. And there was also no makefile, unlike older MFC versions.
I've decided to compile a static MFC library. In this case linker would ignore all extra/unnecessary files I could add into the project by mistake. Created a new Win32 project, selected "Use MFC as a static library", added the whole "src\mfc" directory except for dll*.cpp and localized resource files - and the project compiled successfully! But after adding the generated MFC.lib to a project - got errors complaining on the AfxRegisterMFCCtrlClasses. 
Googling on that function gave a link to a Microsoft blog describing its purpose. But there was no such function in whole MFC sources! After looking into the x86 uafxcwd.lib I've got that it is implemented in the afxctrlcontainer2.obj, so the file is probably named afxctrlcontainer2.cpp. Obviously I have not found that file. Several other functions were not present too:
CMFCControlContainer::UTF8ToString_AfxDispatchCall (it is implemented in x86/x64 ASM, and I was too lazy to rewrite it in THUMB), seems that they deal with MFC and OLE controls embedded into dialog resources. It would not be difficult to reimplement them by looking in disasm or implementation in older MFC versions, but I'm too lazy to do that myself.
I don't need OLE or MFC controls in my dialogs - so I've defined _AFX_NO_MFC_CONTROLS_IN_DIALOGS in stdafx.h of my project, and implement those functions as stubs.

Here is the code of all stubs:

    void __cdecl AfxRegisterMFCCtrlClasses(void)
    {
    }
    extern "C" int __afxNoMFCControlContainerInDialogs=1;
    extern "C" DWORD_PTR AFXAPI
    _AfxDispatchCall(AFX_PMSG pfn, void* pArgs, UINT nSizeArgs)
    {
       __debugbreak();
       return 0;
    }
    int __cdecl CMFCControlContainer::UTF8ToString(char const *,class 
        ATL::CStringT<wchar_t,class StrTraitMFC<wchar_t,
        class ATL::ChTraitsCRT<wchar_t> > > &,int)
    {
       __debugbreak();
       return 0;
    }

After adding that code to MFC lib sources - my project compiled and works correctly on Windows RT.
Debug MFC library is 157 Mb in size, and release version is 1.2 Gb. This is much more than the same x86 LIBs. Probably this is due to embedded debugger and incremental linker information. 

The compiled LIB files are published in this post on XDA. Do not forget to add 
    #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS 
to your stdafx.h and avoid using custom MFC controls in dialog designer.

Added on 28 april:
There is an implementation of UTF8ToString and AfxRegisterMFCCtrlClasses functions here:
  https://github.com/mpc-hc/mpc-hc/blob/master/src/thirdparty/mfc/afxctrlcontainer.cpp
And here I've found the THUMB implementation of _AfxDispatchCall function:
  http://computer-programming-forum.com/86-vc-windows-ce/dc1b0159dbb16d4e.htm
It is probably taken from Windows CE MFC library.
I've recompiled MFC libs with that code, uploaded sources and libs here:
https://drive.google.com/folderview?id=0B25hIeyRmniUZzk0c3hNZmVDSms&usp=sharing

Added on 7 may:
danesh110 on XDA found that beta version of Visual Studio 2012 (it was called Visual Studio 11) contained the MFC libraries and DLLs for Windows RT. More info here: http://forum.xda-developers.com/showthread.php?p=41133829#post41133829
VS 11 beta can be downloaded from the links in this blog: http://www.kunal-chowdhury.com/2012/03/download-visualstudio11-beta.html
Beta has more sources, for example the managed mfc and ARM assembler version of _AfxDispatchCall function, but they are still incomplete.

Комментариев нет: