Thursday, May 29, 2008

Porting old projects to WTL8

Hi,
after upgraded to WTL 8.0 if you try to compile old project you'll get errors like these:

error C2668: 'lstrlenA' : ambiguous call to overloaded function ...\WTL80\include\atlapp.h 697
error C2514: 'size_t' : class has no constructors ...\WTL80\include\atlapp.h 73e
error C3861: 'lstrcpynA': identifier not found ...\WTL80\include\atlapp.h 74


The way to fix it is simple, just add:
#if _ATL_VER == 0x900
#define _SECURE_ATL 1
#endif

just before the include of atlapp.h

:)

Wednesday, May 28, 2008

Inject Dlls

Hi,
today i'll explain how inject dlls into another process.

To inject external dlls into the processes we need to use some functions exported from coredll.dll. These functions are documented in Platform Builder but not in SDK so we need to declare them as extern:
extern "C"
{
BOOL __stdcall SetKMode(BOOL fMode);
DWORD __stdcall SetProcPermissions(DWORD);
LPVOID __stdcall MapPtrToProcess (LPVOID lpv, HANDLE hProc);
struct CALLBACKINFO
{
HANDLE m_hDestProcess;
FARPROC m_pFunction;
PVOID m_pFirstArgument;
};
DWORD __stdcall PerformCallBack4(CALLBACKINFO *pcbi, DWORD dw1, DWORD dw2, DWORD dw3);
}


After declared the undocumented functions we need to write code to use them to inject dlls, so:

//change the kernelmode and the permission for our code
BOOL bMode = SetKMode(TRUE);
DWORD dwPerm = SetProcPermissions(0xFFFFFFFF);

CALLBACKINFO cbi;
cbi.m_hDestProcess = hProcess;
cbi.m_pFunction = (FARPROC)MapPtrToProcess(GetProcAddress(GetModuleHandle(L"COREDLL"), L"LoadLibraryW"), hProcess);
cbi.m_pFirstArgument = (LPVOID)MapPtrToProcess(lpszFullPathDll, GetCurrentProcess());
HINSTANCE hInst = (HINSTANCE)PerformCallBack4(&cbi, 0,0,0); //returns the HINSTANCE from LoadLibraryW

//restore kernelmode and permission
SetKMode(bMode);
SetProcPermissions(dwPerm);


Some details:
hProcess: is the handle of the process where the dll will be injected;
lpszFullPathDll: is the full path to the dll which must be injected;

After a dll is injected into the hProcess we can call every exported function with the same method:

//get the proc address
FARPROC pHook = GetProcAddress(hInst, (LPCTSTR)L"ExportedFunction");
cbi.m_hDestProcess = hProcess;
cbi.m_pFunction = (FARPROC)MapPtrToProcess(pHook, hProcess);
cbi.m_pFirstArgument = NULL; //here we can pass any argument for our 'ExportedFunction'
DWORD dw = PerformCallBack4(&cbi, 0, 0, 0);//returns the same value of 'ExportedFunction'


And finally, as we loaded the dll, we can unload it calling 'FreeLibrary':

cbi.m_hDestProcess = hProcess;
cbi.m_pFunction = (FARPROC)MapPtrToProcess(GetProcAddress(GetModuleHandle(L"COREDLL"), L"FreeLibrary"), hProcess);
cbi.m_pFirstArgument = hInst; //HINSTANCE returned by LoadLibrary
DWORD dw = PerformCallBack4(&cbi, 0,0,0); //returns 1 if correctly unloaded


Enjoy!
:)

Tuesday, May 27, 2008

An alternative to the SHMENUBAR resource

The SHMENUBAR resource is a pain. A real pain. Why is there no support for this on the VS 2005 / 2008 resource editor? This resource is actually quite powerful when it comes to defining the WM application menu and fine-tuning its appearance. But when you need to change something, you need to remember the string table IDs, the toolbar button options and all that.

Most WM applications I have seen so far use a popup menu attached to each of the menu bar buttons. If this is your case, you can forget about the SHMENUBAR resource and use the menu editor. Create a menu with two items and their popups on the resource editor. If you are using WTL, go to your CMainFrame::OnCreate method and instead of the simple

CreateSimpleCEMenuBar();

write:

CreateSimpleCEMenuBar(IDR_MAINFRAME, SHCMBF_HMENU);

The IDR_MAINFRAME is your main menu ID. And that's all you need.

If you are using straight API calls, when calling the SHCreateMenuBar API, make sure that the dwFlags member of the SHMENUBARINFO contains the SHCMBF_HMENU flag and that nToolbarId contains your menu ID.

Thursday, May 22, 2008

WTL - Create a dialog without resource

Hi,
yesterday i explained how create a menu by code without use resource, today i'll explain how to create a dialog without use resource using WTL in 2 mins and with 20 lines :)

WTL framework comes with two classes:
CMemDlgTemplate (which define our dialog template)
CIndirectDialogImpl (which define our dialog class)

In the code below i'll show how create an empty dialog with just few lines:


#pragma once
#include <atldlgs.h> //don't forget it :)

typedef
CWinTraits<WS_VISIBLEWS_POPUPDS_CENTER> MyDlgTraits;
class
CAboutDlg : public CIndirectDialogImpl<CAboutDlg, CMemDlgTemplate,
CStdDialogImpl<CAboutDlg>>
{
public:
//ovverride the DoInitTemplate and set the correct values for template
void
DoInitTemplate()
{
m_Template.Create(false, L"OUR DIALOG CAPTION", 0, 0, 0, 0,
MyDlgTraits::GetWndStyle(0),
MyDlgTraits::GetWndExStyle(0));
}

BEGIN_MSG_MAP(CAboutDlg)
MESSAGE_HANDLER(WM_INITDIALOG,
OnInitDialog)
CHAIN_MSG_MAP(CStdDialogImpl)
END_MSG_MAP()

LRESULT
OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL&
bHandled)
{
#ifdef
WIN32_PLATFORM_PSPC
AtlCreateEmptyMenuBar(m_hWnd);
#endif
return
bHandled = FALSE;
}
};


I used CStdDialogImpl as base class which is the specific base dialog for devices.

Bye

Wednesday, May 21, 2008

Create Menu Bar Programmatically - WM5

Hi,
today i show you how create a menubar from code without use any resource.

//add these lines in your wm_initdialog or wm_create function
#define ID_CHANGE_TEXT WM_APP+1
#define ID_ADD_NEW_ITEM WM_APP+2
#define ID_NEW_ITEM WM_APP+3

//Create the right popupmenu
HMENU hPopupRightMenu = ::CreatePopupMenu();
::InsertMenu(hPopupRightMenu, -1, MF_BYPOSITION, ID_CHANGE_TEXT, L"Change Left Text");
::InsertMenu(hPopupRightMenu, -1, MF_BYPOSITION, ID_ADD_NEW_ITEM, L"Add New Item here");
//create the toolbar menu
HMENU hMenu = ::CreateMenu();
::InsertMenu(hMenu, 0, MF_BYPOSITION, IDOK, L"Left");
::InsertMenu(hMenu, 1, MF_BYPOSITIONMF_POPUP, (UINT)hPopupRightMenu, L"Right");
//and now create the menu bar
HWND hMB = AtlCreateMenuBar(m_hWnd, (UINT)hMenu, SHCMBF_HMENU);

now add handlers for our menus id:
LRESULT OnChangeText(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
//try to modify text on the left button
TBBUTTONINFO tbbit = {0};
tbbit.cbSize = sizeof(tbbit);
tbbit.dwMask = TBIF_TEXT;
tbbit.pszText = L"Exit";
::SendMessage (SHFindMenuBar(m_hWnd), TB_SETBUTTONINFO, (UINT)IDOK, (LPARAM)&tbbit);
return 0;
}

LRESULT OnAddNewItem(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
//now try to modify right popup
TBBUTTONINFO tbbi = {0};
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_LPARAM;
::SendMessage (SHFindMenuBar(m_hWnd), TB_GETBUTTONINFO, (WPARAM)0, (LPARAM)&tbbi);
HMENU hPopupMenu = (HMENU)tbbi.lParam;
InsertMenu(hPopupMenu, -1, MF_BYPOSITION, ID_NEW_ITEM, L"New Item!");
return 0;
}

LRESULT OnNewItem(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
MessageBox(L"New Item Clicked!!!");
return 0;
}


this is ... :)

Tuesday, May 20, 2008

POOM: 'unresolved external symbol' or 'already defined'

Often when we use POOM api's we get those errors by compiler.
We have two methods to fix it:

solution a
- include only where you need;
- include into only one .cpp file:
#define INITGUID
#include <initguid.h>
#include <pimstore.h>
#pragma comment(lib, "pimstore.lib") //don't forget to link library ;)


solution b
- include where you need:
#include <pimstore.h>
#pragma comment(lib, "pimstore.lib") //don't forget to link library ;)

- replace the IID_* and CLSID_* with the __uuidof([interface]) sentence
so:
CLSID_Application ==> __uuidof(Application)
IID_IItem ==> __uuidof(IItem)
IID_IPOutlookApp ==> __uuidof(IPOutlookApp)
and so on...



I hope this help you

Thursday, May 15, 2008

Welcome

Welcome to the Windows Mobile Developers Blog!