Archive for October, 2006

Annoyances with IE7

Sunday, October 22nd, 2006

Since installing IE7, I’ve ran into a couple of annoyances.

The largest of which is that you can no longer use the trick to to launch an instance of iexplore.exe under Run As, and then navigate to the Control Panel to get an administrator view of Control Panel if you are logged on as a limited user (for pre-Vista). Now, instead, the admin IE instance will just tell the already-running explorer instance (which is running as your limited user account) to open a window at Control Panel. This is of course not what I want, which leaves me stuck with remembering the names of the individual .cpl files and launching them from an admin. Unfortunately for me, this just made running as a limited user on Windows XP and Windows Server 2003 much more painful; not a good thing from the perspective of a browser that is supposed to make things more secure. (In case you were wondering, you can’t just launch an admin explorer.exe while you already have explorer running under your user account. If you try to do this, the admin explorer instance will tell the already running explorer instance to open a new window, and then exit.) Alternatively, I could configure explorer to use a different process for every window, which does actually allow you to run explorer directly with Run As, but this has the unfortunate side effect of dramatically increasing memory usage if you have multiple explorer folder windows open.

The other things I have ran into so far are site compatibility problems, like lists breaking for WordPress. I am not sure if this particular problem is a WordPress one or an IE7 one, having not been particularly inclined to delve into HTML DOM debugging, but WordPress does appear to validate cleanly under the W3C XHTML validator. Some compatibility things are to be expected, of course, but it’s a bit disappointing to see them so glaringly obvious without either WordPress or Microsoft having done something to fix (or even acknowledge) the problem by now. Sigh.

As for tabbed browsing, I’m not sure if I really like this much yet. Up till now, I’ve pretty much always used “old-fashioned”, windowed browsing. I’ll see if tabbed browsing grows on me, but I wish I didn’t have to sacrifice ease of running as non-admin for it…

(Update: a commenter, jpassing, suggested using “explorer.exe /separate” with Run As, which appears to work nicely as a replacement for starting iexplore.exe when IE7 is installed.)

Heading to Redmond…

Saturday, October 21st, 2006

I’m going out to Redmond for this coming week for a Vista compatibility lab focused on helping ISVs with getting their applications running well on Vista. I’ll try to keep the blog updated with anything interesting that I find out on the way. Besides the standard stuff about UAC and non-admin users, I’m hoping to get some more obscure and difficult things cleared up that I have thus far never really got an answer to, such as how some of the UAC changes to how tokens work will affect the ability to alter network credentials of running processes.

Unordered list items broken on the blog in IE7

Saturday, October 21st, 2006

Taking a little segway from the usual topics on the blog, today I got around to installing IE7 for the first time. Unfortunately, it seems that I have run into my first site compatibility issue that I really care about: a problem with WordPress.

For some reason, unordered list items appear to be not showing up as bulleted items on the blog when you are using IE7. The list items are still indented, but they don’t have a bullet prefixing them (just whitespace). I haven’t yet spent much time debugging this issue, which is for now just a minor annoyance. It doesn’t seem to be specific to my blog, as IE7 is having this problem for me with other WordPress blogs.

For example, when using IE7, these list items do not have bullet prefixes presently:

  • test list item 1
  • test list item 2

Anyone have a workaround or fix for this particular annoyance? Comment away if so…

Win32 calling conventions: __stdcall in assembler

Friday, October 20th, 2006

It’s been awhile since my last post, unfortunately, primarily due to my being a bit swamped with work and a couple of other things as of late. With that said, I’m going to start by picking up where I had previously left off with the Win32 calling conventions series. Without further ado, here’s the stuff on __stdcall as you’ll see it in assembler…

Like __cdecl, __stdcall is completely stack-based.  The semantics of __stdcall are very similar to __cdecl, except that the arguments are cleaned off the stack by the callee instead of the caller.  Because the number of arguments removed from the stack is burned into the target function at compile time, there is no support for variadic functions (functions that take a variable number of arguments, such as printf) that use the __stdcall calling convention.  The rules for register usage and return values are otherwise identical to __cdecl.

In practice, this typically means that an __stdcall function call will look much like a __cdecl function call until you examine the ret instruction that returns transfer to the caller at the end of the __stdcall function in question.  (Alternatively, you can look to see if it appears as if stack arguments are cleaned after the function call.  However, the compiler/optimizer sometimes likes to be tricky with __cdecl functions, and defer argument removal until several function calls later, so this method is less reliable.)

Because the callee cleans the arguments off the stack in an __stdcall function, you will always[1] see a ret instruction terminating a __stdcall function.  For most functions, this count is four times the number of arguments to the function, but this can vary if arguments that are larger than 32-bits are passed.  On Win32, this argument count in bytes value is virtually always[2] a multiple of four, as the compiler will always generate code that aligns the stack to at least four bytes for x86 targets.

Given this information, it is usually fairly easy to distinguish an __stdcall function from a __cdecl function, as a __cdecl function will never use an argument to ret.  Note that this does imply, however, that it is generally not possible to disinguish between an __stdcall function and a __cdecl function in the case that both take zero arguments (without any other outside information other than disassembly); in this special case, the calling conventions have the same semantics.  This also means that if you have a function that does not clean any bytes off the stack with ret, you’ll technically have to examine any callers of the function to see if any pass more than zero arguments (or the actual function implementation itself, to see if it ever expects more than zero arguments) in order to be absolutely sure if the function is __cdecl or __stdcall.

Here’s an example of a simple __stdcall function call for the following C function:
 

__declspec(noinline)
int __stdcall StdcallFunction1(int a, int b, int c)
{
 return (a + b) * c;
}

If we call the function like this:

StdcallFunction1(1, 2, 3);

… we can expect to see something like so, for the call:

push    3
push    2
push    1
call    StdcallFunction1

(There will be no add esp instruction after the call.)

This is quite similar to a __cdecl declared function with the same implementation.  The only difference is the lack of an add esp instruction following the call.

Looking at the function implementation, we can see that unlike the __cdecl version of this function, StdcallFunction1 removes the arguments from the stack:

StdcallFunction1 proc near

a= dword ptr  4 b= dword ptr  8 c= dword ptr  0Ch mov     eax, [esp+8] ; eax = b mov     ecx, [esp+4] ; ecx = a add     eax, ecx     ; eax = eax + ecx imul    eax, [esp+c] ; eax = eax * c retn    0Ch          ; (return value = eax) StdcallFunction1 endp

As expected, the only difference here is that the __stdcall version of the function cleans the three arguments off the stack.  The function is otherwise identical to the __cdecl version, with the return value stored in eax.

With all of this information, you should be able to rather reliably identify most __stdcall functions.  The key things to look out for are:

  • All arguments are on the stack.
  • The ret instruction terminating the function has a non-zero argument count if the number of arguments for the function is non-zero.
  • The ret instruction terminating the function has an argument count that is at least four times the number of arguments for the function.  (If the count is less than four, then the function might be a __fastcall function with three or more arguments.  The __fastcall calling convention passes the first two 32-bit or smaller arguments in registers.)
  • The function does not depend on the state of the ecx and edx volatile variables.  (If the function expects these registers to have a meaningful value initially, then the function is probably a __fastcall or __thiscall function, as those calling conventions pass arguments in the ecx and edx registers.) 

In the next post in this series, I’ll cover the __fastcall calling convention (and hopefully it won’t be such a long wait this time).  Stay tuned…

 

[1]: For functions declared as __declspec(noreturn) or that otherwise never normally return execution control directly to the caller (i.e. a function that always throws an exception), the ret instruction is typically omitted.  There are a couple of other rare cases where you may see no terminating ret, such as if there are two functions, where one function calls the second, and both have very similar prototypes (such as argument ordering or an additional defaulted argument).  In this case, the compiler may combine two functions by having one perform minor adjustments to the stack and then “falling through” directly to the second function.

[2]: If you see a function with a ret instruction that does not take a multiple of four as its argument, then the function was most likely hand-written in assembler.  The Microsoft compiler will never, to my knowledge, generate code like this (and neither should any sane Win32 compiler).