Saturday, March 24, 2007
CreateDialog, CreateWindow or any other window\dialog creation function fails and GetLastError is 0
Thursday, March 01, 2007
ASSERT, ASSERT and ASSERT. Also, always ASSERT !
I constantly find its importance in my coding.
It is very important to always assert your variables\conditions along with the testing it ( 'if' statement ).
Also, another common use is in an algorithm. it is important to assert different conditions which might define a state at a moment, a state which I know it should be false\true (when i mean a state i mean a condition composed of multiple variables, variables which might not be in the same scope but I expect some specific values).
i am having situations where while coding, i come accross some asserts which make me say "wtf, how did that happen ?" and then i discover that the algo has some issues which were not obvious due to complexity (or my fatigue).
Friday, February 16, 2007
mozilla build from source code
--------------------------------------------------
Get source code from
https://developer.mozilla.org/en/Download_Mozilla_Source_Code
Copy the firefox-1.5-source.tar.tar in e:\
Create a directory called e:\mozilla
Extract the firefox-1.5.source.tar.tar into mozilla directory
2. install cygwin
--------------------------------------------------
run http://www.cygwin.com/setup.exe
choose the first type of install (the first form with the 3 radio-buttons) and choose "DOS" style line endings
as you read the http://developer.mozilla.org/en/docs/Windows_Build_Prerequisites you see that
you need to make sure that the cygwin packages include these:
ash -- UNIX-like command line interpreter shell (Base category)
coreutils -- GNU core utilities (includes fileutils, sh-utils, and textutils) (Base category)
diffutils -- file comparison utility (Base category)
findutils (Base category)
gawk -- pattern matching language (Base and Interpretors categories)
grep -- text search tool (Base category)
make -- dependency analyzer for software builds (Devel category)
patchutils -- a small collection of programs that operate on patch files (Devel category)
perl -- a scripting language used to control parts of the build (Interpreters category)
sed -- a search and replace language (Base category)
unzip -- zip file extraction (Archive category)
zip -- zip file creation (Archive category)
( u need to click if the package is marked as Skipped and choose latest version (some packages have multiple versions))
3. setup environment variables
--------------------------------------------------
create a file called 1.bat near the cygwin.bat, in c:\cygwin
put the followin content in 1.bat (attention to the VS.net paths and others if necessary)
@echo off
rem --- Basic config, with VC7 libIDL files
SET MOZ_TOOLS=C:\moztools
SET GLIB_PREFIX=C:\vc71
SET LIBIDL_PREFIX=C:\vc71
SET MINGWBASE=C:\Dev-Cpp
SET CYGWINBASE=C:\cygwin
rem --- Clean slate start
SET INCLUDE=
SET LIB=
SET PATH=C:\;C:\windows\system32;C:\windows;C:\windows\system32\wbem
rem --- Set VC7 compiler environment vars
CALL "C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\vcvars32.bat"
rem --- Then prepend Cygwin path
SET PATH=%CYGWINBASE%\bin;%PATH%
rem --- Add glib/libidl to build environment
SET PATH=%PATH%;%GLIB_PREFIX%;%GLIB_PREFIX%\bin
SET INCLUDE=%GLIB_PREFIX%\include;%INCLUDE%;%MINGWBASE%\include
SET LIB=%GLIB_PREFIX%\lib;%LIB%
rem -- moztools comes last after glib/libIDL
SET PATH=%PATH%;%MOZ_TOOLS%\bin
4. edit the c:\cygwin\cygwin.bat
--------------------------------------------------
add the following line at the beginning of the cygwin.bat content
call 1.bat
cygwin.bat should now like this:
@echo off
call 1.bat
C:
chdir C:\cygwin\bin
bash --login -i
5. create a folder called C:\vc71
--------------------------------------------------
get the http://ftp.mozilla.org/pub/mozilla.org/mozilla/source/wintools.zip
and extract the content in c:\vc71
only 3 dirs are needed: bin, include and lib
so the content of c:\vc71 should be:
c:\vc71\bin
c:\vc71\include
c:\vc71\lib
this dirs are the
SET GLIB_PREFIX=C:\vc71
SET LIBIDL_PREFIX=C:\vc71
from the 1.bat file
also, read the 'Netscape wintools' section from http://developer.mozilla.org/en/docs/Windows_Build_Prerequisites
install.bat needs to be run
6. create a file called 'mozconfig' in E:\mozilla with the following content:
--------------------------------------------------
mk_add_options MOZ_CO_PROJECT=all
ac_add_options --enable-application=browser
ac_add_options --disable-optimize
ac_add_options --enable-debug
this is taken from: http://developer.mozilla.org/en/docs/Configuring_Build_Options
read the instructions
7 build it !
--------------------------------------------------
run the cygwin.bat from c:\cygwin
make sure that at the top you see some comments from the vsvars32.bat (this means the environment variables are set)
type:
make -f client.mk build_all
in order to do a cleanup after a build, type
make -f client.mk clobber_all
if errors are encountered, use the http://developer.mozilla.org/en/docs/Mozilla_Build_FAQ
for example, it is possible that this error to appear (at least i got it):
configure: error: the linker major version, , does not match the compiler suite version, 6.
The cygwin tool "link.exe" is being confused for an object linker.
Make sure that the Microsoft tools are before cygwin in your PATH, or rename or remove /bin/link.exe
as it says i needed to rename the c:\cygwin\link.exe to link__.exe
Thursday, February 15, 2007
threading on GDI objects
When you dealing with multithreading in your code, every data you use in more than one thread it should be a subject to your attention in the way its used in those threads.
Similary, using GDI objects in multithreading does not require any special code beside some (natural) common-sense 'not to do' things, which is, dont read and modify un-synchronized in the same time. Also, remember that they have thread affinity (the thread which created the object should be the one who deletes it).
The following text is from the Raymond Chen wonderful blog:
Window objects: thread which created the window its said to be the window 'owner'.
Messages are dispatched to a window procedure only on the thread that owns it, and generally speaking, modifications to a window should be made only from the thread that owns it. Although the window manager permits any thread to access such things as window properties, styles, and other attributes such as the window procedure, and such accesses are thread safe from the window manager's point of view, load-modify-write sequences should typically be restricted to the owner thread. Otherwise you run into race conditions such as the following:
wpOld = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)newWndProc);
LRESULT CALLBACK newWndProc(...)
{
... CallWindowProc(wpOld, ...); ...
}
If modifications to the window procedure are made carelessly from any thread, then between the first two lines, a second thread may change the window procedure of the window, resulting in newWndProc passing the wrong "previous" window procedure to CallWindowProc.
Why, then, does Windows even allow a non-owner thread from changing the window procedure in the first place? Because, as we all know, 16-bit Windows was a co-operatively multi-tasked system, which means that one thread could do anything it wanted secure in the knowledge that no other thread would interrupt it until it explicitly relinquished control of the CPU. Therefore, the above code sequence was safe in 16-bit Windows. And for compatibility reasons, the code continues to be legal, even though it isn't safe any more. (Note, however, that in an attempt to limit the scope of the damage, the window manager allows only threads in the process that owns the window to change the window procedure. This is a reasonable limitation since separate address spaces mean that function addresses in other processes are meaningless in the process that owns the window anyway.)
Device contexts:
Device contexts (DCs) also have a certain degree of thread affinity. The thread that calls functions such as GetDC must also be the one that calls ReleaseDC, but as with window handles, during the lifetime of the DC, any thread can use it, but one at a time. If you choose to use a DC in a multi-threaded manner, it's your responsibility to coordinate the consumers of that device context so that only one thread uses it at a time. For example, to host windowless controls across multiple threads, the host obtains a DC on the host thread, then asks each control in sequence to draw itself into that DC. Only one control draws into the DC at a time, even if the control happens to be on a different thread.
Menus:
Menus do not have thread affinity. Any thread can use a menu. However, if two threads use a menu, it is the responsibility of those threads to coordinate among themselves how that menu will be used, so that one thread doesn't modify a menu while another is busy displaying it, for example.
Icons, cursors, and accelerator tables behave like menus. They do not have thread affinity. They are easier to manage than menus since they cannot be modified once created, so the only thing you have to worry about is not to use one after it has been destroyed
GDI objects are much simpler. As a general rule, they all have process affinity: They can be used by any thread in the process that created them. If you use a GDI object from multiple threads, it is your responsibility to coordinate the object's use.
Note that the window manager and GDI as a general rule keep their respective objects thread-safe. When I say that it is your responsibility to coordinate an object's use from multiple threads, I mean that you have to coordinate among your own threads if you're going to modify the object from one thread and read from it on another or modify it from two threads. For example, if one thread enumerates a menu while another is modifying it, the one doing the enumeration will get inconsistent results. Similarly, if two threads both try to change a menu item at the same time, the last writer will win.
http://blogs.msdn.com/479124.aspx
http://blogs.msdn.com/479587.aspx
http://blogs.msdn.com/480064.aspx
Monday, January 08, 2007
IHTMLFormElement::get_elements fails
Don't blow your head, you have this situation:
you have a valid form element and you want to access its elements.
IHTMLFormElement* pForm = ...
one way to do it is by:
HRESULT IHTMLFormElement::get_elements(IDispatch **p)
and the code looks like the following:
IDispatch* pDisp = NULL;
pForm->get_elements(&pDisp);
IHTMLElementCollection* pFormColl = NULL;
HRESULT hr = pDisp->QueryInterface(IID_IHTMLElementsCollection, (void**)&pFormColl);
but you get pFormColl having NULL value and hr = 0x80004002 which means
The QueryInterface method did not recognize the requested interface. The interface is not supported.
Google'ing it a bit you get plenty of similar behaviour. The workaround is to use
HRESULT IHTMLElement::get_children(IDispatch **p)
The hint is given by MSDN description for this method: IHTMLElementCollection* pChildrenElem = NULL;
To access all elements contained in a form, call QueryInterface on IHTMLFormElement and request an IHTMLElement interface. Use the IHTMLElement::children property of the IHTMLElement interface to retrieve a collection of all elements in the form
So, translated into code:IHTMLElement* pElem = NULL;
pFormElem->QueryInterface(IID_IHTMLElement, (void**)&pElem);
pElem->get_children(&pChildrenElem);
After all, this should be your preferred way since MSDN also says that you do not get actually all the form elements if you use IHTMLFormElement::get_elements :
The collection retrieved by the IHTMLFormElement::get_elements property does not include input type=image elements from a form
So, in order to obtain a IHTMLFormElement children elements, use IHTMLElement method instead.
Friday, December 22, 2006
Conversion macros\inline functions
for example, consider this:
you have a dialog window procedure and you want to handle WM_CTLCOLOREDIT message to change the background color of the edit control.
BOOL CALLBACK DialogProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch(uMsg)
{
case WM_CTLCOLOREDIT:
return (BOOL)(GetStockObject(DKGRAY_BRUSH));
}
}
I followed the instructions from MSDN for WM_CTLCOLOREDIT:
"If a dialog box procedure handles this message, it should cast the desired return value to a BOOL and return the value directly."
the problem is it works but it gives a warning: Compiler Warning (level 1) C4311.
"This warning detects 64-bit portability issues. For example, if code is compiled on a 64-bit platform, the value of a pointer (64 bits) will be truncated if it is assigned to an int (32 bits). This warning is only issued when /Wp64 is used. "
I am using VisualC++ 2003 compiler so it seems /wp64 is put by default.
Now, MS made some inline conversion functions which must be used when converting data types.
this if found in intsafe.h header.
additional information can be found in a blog of a MS security guy:
http://blogs.msdn.com/michael_howard/archive/2006/02/02/523392.aspx
additionally, look at this info:
"Rules for Using Pointers" in MSDN
There are also some other conversion macros in Basetsd.h header made for win64 programming too:
void * Handle64ToHandle( const void * POINTER_64 h )
void * POINTER_64 HandleToHandle64( const void *h )
long HandleToLong( const void *h )
unsigned long HandleToUlong( const void *h )
void * IntToPtr( const int i )
void * LongToHandle( const long h )
void * LongToPtr( const long l )
void * Ptr64ToPtr( const void * POINTER_64 p )
int PtrToInt( const void *p )
long PtrToLong( const void *p )
void * POINTER_64 PtrToPtr64( const void *p )
short PtrToShort( const void *p )
unsigned int PtrToUint( const void *p )
unsigned long PtrToUlong( const void *p )
unsigned short PtrToUshort( const void *p )
void * UIntToPtr( const unsigned int ui )
void * ULongToPtr( const unsigned long ul )
look in MSDN here for more info.
For the above code, the inline conversion function to use is:
case WM_CTLCOLOREDIT:
return HandleToLong(GetStockObject(DKGRAY_BRUSH));
or:
case WM_CTLCOLOREDIT:
return (BOOL)(INT_PTR)(GetStockObject(DKGRAY_BRUSH));
Thursday, December 21, 2006
Using photoshop to create & edit ICO files
After installing the plugin file in the Photoshop directory (installing means just copy the ICOFormat.8bi file into the Photoshop plugin directory so it can load it at startup; mine is: C:\Program Files\Adobe\Adobe Photoshop CS\Plug-Ins\File Formats\ICOFormat.8bi)
to create an icon in Photoshop:
1. select your object which you want to appear in your icon with the Magic Wand tool (selection).
you might want to adjust the Tolerance factor.
2. go to Selection menu and choose save selection and name the layer Alpha (it can have any name).
3. go to Save menu and now you should have in the list the ICO format available.
Remeber 2 things:
The alpha channel you created must look like this: you should see the object silhouette in black and the background in white.
The icon cannot have in size more than 255x255 pixels (Windows file format limitation).
At the same location (http://www.telegraphics.com.au) there is a tool which can take different icons files and concatenates them into one ico file but i havent tried it.