Category Archives: Code

MapBinder – shake your maps

mapbinder

I have put together preview for visually shaking maps where you don’t get just map layer names, but also preview of layers ! Somehow I couldn’t find any page on internet that would allow you to display layers from GetCapabilities WMS as image thumbnails. I’ve kept this idea for a long time and actually it started with yahoo pipes year ago – why not to visually display GetCapabilities as RSS feed with image thumbnails referenced as media type in the feed ? after little experimenting I realized that the value is in combination of position and WMS information, so the use case is “I am here on this place and hey WMS servers, give me all you know about this place…”

That lead me to the prototype of the site codenamed ‘MapBinder’ that allows you to visually combine WMS layers. Before you jump there, let me put here some credits to projects and people who enabled that – first it isOpenLayers 2.7 plus some sandboxed content that implemented GetCapabilities..I don’t remember exact location, then it is blog on tydlevidle.cz that implemented extension to read mapy.cz (mapy.cz is proprietary web based geoengine for maps like google but is using different projection). The last piece I found on some reference on geocaching.cz where someone pointed on conversion.js JavaScript by Tomas Ebenlendr. I forgot to mention that MapBinder is now synced with mapy.cz since it would be hard to overlay mapy.cz with JTSK-based projection, I have decided that reprojection will be done by user’s brain – having side by side maps – everyone can benefit from the content even they do not overlay.

Map Binder can be found on page: updated 07/2025 :https://www.sumbera.com/lab/wms25/wms25.html

. Feel free to save it and examine it. I believe that from this point desktop and web readers of WMS layers will display thumbnails for better user experience :).

How to run in parallel executable graphicaly intensive applications on Win32

code

Example of settings for 10 concurrent processes runing in batch mode:

1. Graphical Application could take cca 250 KB per instance from desktop heap, that is 2.5 MB for 10 running executables. Thus desktop heap for non interactive services should be set to 3072 KB if you want to run 10 Applications. You set it in registry key:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\
\SubSystems\Windows%SystemRoot%\system32\csrss.exe
ObjectDirectory=\Windows SharedSection=1024,3072,3072 …

2. Total desktop heap per session is controlled by SessionViewSize. The size depends on total number of services you run. For instance running 10 services as domain user in session0 + default desktop + logon would give the minimum size around 30MB, set it to 42 MB ( decimal value !)

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management
DWORD key SessionViewSize = 42

3. GDIs most likely use area of paged pool for the session, so set parameter SessionPagedSize to 128 MB.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management
DWORD key SessionPoolSize = 128

4. SessionPagedSize + SessionViewsSize should not exceed 450MB, however downside is decreasing other memory areas used by the system in it’s 2GB space (like system cache )

5.you should not boot the system with /3GB option *because system space has only 1 GB space, you can not influence SessionSpace size and it is fixed to 20 MB – that imply that you can not run many Applicationse on such system, may be more after turning some services off. Moreover GDI also uses SessionViewSpace and the limit 20 MB is insufficient even for one process running. Check that in c:\boot.ini that there is nothing like /3G

MDL code injection with Detour

Summary: Paper describes how to spy MDL built-in functions with help of Microsoft’s research project called Detour (a binary interception of functions). Enhanced code is available on request…

Downloads: traceapi.zip (source and sample)

Introduction

Programming MDL means sometimes tough time in debug. Sometimes you need to monitor particular function, or sequence of functions and see where this or that memory was allocated or released. Microsoft researches came with tool called Detour – a binary interception of functions. I got idea to test it on MicroStation built-in functions to see how Detour can help MDL developers. Please, read carefully following pages, if you are interested, cause I suppose in this short paper that you know how detours works. http://research.microsoft.com/sn/detours/

How to make the sample work
download traceapi.zip and extract all files to arbitrary folder. you will get TRACEAPI folder with directories bin, inc, lib etc..go to the bin directory and..

1. copy executable files (syelogd.exe, traceapi.dll, withdll.dll,testApi.bat)
from bin directory into MSv8 path (e.g d:\bentleyv8\program\MicroStation)

2. start command prompt and run syelogd.exe – the program will wait for messages
passed from detour:

3. start MS DevShel and inject traceapi.dll into MicroStation process with help of withdll.exe utility:

4. in MicroStation open for instance from menu Settings/manage dialog box and see what have been traced in syelogd process:

note that in code only these functions are traced for this sample:

API_TRACE_DO(mdlDialog_open);
API_TRACE_DO(mdlDialog_openAdvisoryBox);
API_TRACE_DO(mdlDialog_openAlert);
API_TRACE_DO(mdlDialog_openAlertById);
API_TRACE_DO(mdlDialog_openCompletionBar);
API_TRACE_DO(mdlDialog_openInfoBox);
API_TRACE_DO(mdlDialog_openInfoBoxOptional);
API_TRACE_DO(mdlDialog_openMessageBox);
API_TRACE_DO(mdlDialog_openModal);
API_TRACE_DO(mdlDialog_openModalWithMD);
API_TRACE_DO(mdlDialog_openModalWithMDAndBsiDataP);
API_TRACE_DO(mdlDialog_openOKCancelBoxOptional);
API_TRACE_DO(mdlDialog_openPalette);
API_TRACE_DO(mdlDialog_openWithDBQuery);
API_TRACE_DO(mdlDialog_openWithMD);

..but you may extend them….with code modification

5. open VisualStudio project tr.dsw and add your custom function into file
_mdlv8.cpp. This can be done in two ways either Detour’s verbose way with detail list
of all parameters and your custom condition for displaying output
or by extended simplified way with macros API_TRACE_DEC and API_TRACE_DO

enjoy it !

following is brief info how Detour works and what have been modified….

Original Detour steps

Originally Detour needs several definitions to get inside the specified API function, let’s look on subclassing mdlElmdscr_freeAll function:

 1. first define maping between real function and original DLL API function

DETOUR_TRAMPOLINE(int Real_mdlElmdscr_freeAll(MSElementDescr **elmDscrPP),mdlElmdscr_freeAll);

2. Define *user hook* function from which original function will be called. This function is jumped from code inserted in front of the original DLL function. When any application call MDL built-in function mdlElmdscr_freeAll, the jump instruction cause redirection into your user function, see fig. bellow:

int Mine_mdlElmdscr_freeAll(MSElementDescr **elmDscrPP)
{
int type=0; 
if (*elmDscrPP)
type = (*elmDscrPP)->el.ehdr.type;
if (type == 4){
_PrintEnter("LINE : mdlElmdscr_freeAll(%lx)\n", *elmDscrPP);
}
int rv = 0;
__try {
rv = Real_mdlElmdscr_freeAll(elmDscrPP);
} __finally {
if (type == 4){
_PrintExit("LINE :mdlElmdscr_freeAll() <- %lx\n", rv);
}
};
return rv;
}

4. last step is to inject code and set which user function will be used

DetourFunctionWithTrampoline((PBYTE)Real_mdlElmdscr_freeAll,(PBYTE)Mine_mdlElmdscr_freeAll);

As you may see, you have to write several lines of code, unfortunatelly…Anyhow this approach is good, if you need only several function to monitor, if you need to change one function or like this. But if you need to spy hundreds or thousands MDL built-in functions, then you may got trouble with definition and declaration of all these functions. How to deal with this ? I decided to little bit enhance Detour with capability if spying dll functions without knowledge of its parameters (or if you do not need to monitor them). And this was good chance to remember Assembler.

There are several problems:

– you need to somehow save all parameters,

– you need to save all registry,

– you cannot influence current stack frame of the function,

– you need take care of threads.

– But still it would be nice to print some values of function parameters –at least in hex format

Enhancement of Detour:

These functions performs second stack push and pop operation to save state of stack.

#define STACK_FRAME_SIZE 0x38//0x78 for debug
VOID _push (VOID){
DWORD *threadStackP = (DWORD*)TlsGetValue(s_nTlsStack)+ sizeof(DWORD);
_asm mov edx,dword ptr [threadStackP]
_asm mov ecx,[esp+STACK_FRAME_SIZE]
_asm mov [edx],ecx
TlsSetValue(s_nTlsStack,threadStackP );
}
VOID _pop(VOID){
DWORD *threadStackP = (DWORD*) TlsGetValue(s_nTlsStack);
_asm mov ecx,dword ptr [threadStackP]
_asm mov edx,dword ptr [ecx]
_asm mov [esp+STACK_FRAME_SIZE+0x4],edx
TlsSetValue(s_nTlsStack,threadStackP-sizeof(DWORD));
}

this is macro for automatic declaration of user hook function with

printing of parameters

__declspec(naked) Mineg_##target() \
{ \
__asm { pushad };\
_push();\
__asm { popad };\
__asm { add esp,4};\
__asm { pushad };\
__asm { push[esp+0x24]};\
__asm { push[esp+0x28]};\
__asm { push[esp+0x28]};\
__asm { push[esp+0x3C]};\
_PrintEnter("%s -->%08lx \t (%s) \t %08lx \t (%s) \n",#target);\
__asm { add esp,16};\
__asm { popad };\
__asm { call Realg_##target };\
__asm { push 0xFFFFFFFF};\
__asm { pushad };\
__asm { push eax };\
_pop();\
_PrintExit("%s <--- %lx\n",#target);\
__asm { pop eax };\
__asm { popad };\
__asm { ret };\
}
#define API_TRACE_DO(func) \
DetourFunctionWithTrampoline((PBYTE)Realg_##func,(PBYTE)Mineg_##func);

so how it works now ?

you need only 2 lines to get into API function :

//declaration:
API_TRACE_DEC(mdlElmdscr_freeAll);
//definition
API_TRACE_DO(mdlElmdscr_freeAll);

morover I have extended utility RELIEFe (RELIEF exports) which generates from Microstation dll these two lines for each exported function, so the final task is only copy-paste and compile…and enjoy.

here is example of spying of mdlDialog_callFunction with print of calling MDL task. The number on the left is thread number in MicroStation process.

001 mdlDialog_callFunction MDLPROJ ret: 60c1c2cb
001 mdlDialog_callFunction MDLCACHE ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction MDLCACHE ret: 60c1c2cb
001 mdlDialog_callFunction MDLPROJ ret: 60c1c2cb
001 mdlDialog_callFunction MDLPROJ ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction MDLPROJ ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction RELIEF ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction RELIEF ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction RELIEF ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction MDLPROJ ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction MDLPROJ ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction SUNANGLE ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction SUNANGLE ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-
001 mdlDialog_callFunction SUNANGLE ret: 60c1c2cb
001 mdlDialog_callFunction ret 60c1c2cb<-

Final words

I would say, DETOUR is cool, you may intercept nearly any MDL built in function. With enhancement I presented above, you may easily customize code for huge amount of functions (but I would recommend you not to do this, because it naturally slow down MicroStaiton performance) good approach is to take for instance particular area of function, let’s say Window function and see what is going on behind the scene.another utilization of the detour can be in subclassing or changing behavior of MDL API function (may be temporarily), or you may dynamically prohibit execution of the function you don’t like…