Click here to Skip to main content
Email Password   helpLost your password?

Introduction

Normally I log on to my machine as a normal non-admin user. In order to debug ASP.NET applications, one needs to be a member of the administrators group. So I need to launch VS.NET as local administrator. Things work out pretty good except that there is an annoying problem that, when I start debugging of the web application, Internet Explorer does not appear, so I have to launch Internet Explorer separately.

I wrote a small macro which handled the IDE events and launched Internet Explorer when debugging started. The only problem with this solution was that, while debugging there were two ASP.NET sessions running simultaneously and single stepping through the code became confusing (as happens with debugging multithreaded applications). The fact that there were two simultaneous sessions indicated that VS did launch IE. Viewing list of processes did indicate that there was an extra IE instance.

SessView

Why was IE main window not visible? Using the SessView tool by Keith Brown indicated that the invisible IE was launched in a separate non-interactive window station. Each window created in the Windows NT based operating systems belongs to a window station. Only one window station named winsta0 is interactive. Windows that belong to this window station can interact with the user. Window stations can be allocated to a process by the parent process through the CreateProcess function call. The 9th parameter of CreateProcess is of type STARTUPINFO. STARTUPINFO has a parameter called lpDesktop which specifies the name of the window station (and desktop) allocated to the process. Here is how it works:-

  1. If lpDesktop is NULL the newly created process inherits the window station of the calling process.
  2. If lpDestop is an empty string, system allocates the process a unique window station based on the logon session ID of the newly created process. The string is of the form Service-0xX-XXX$.
  3. Otherwise system uses the name of the window station provided in lpDesktop.

All evidences from SessView pointed out that lpDestop parameter passed to CreateProcess when launching IE from VS.NET, was an empty string. So a simple fix would be to intercept CreateProcess calls from within the context of the devenv process and modify this parameter.

Detours

Detours library from Microsoft research is my favorite for API interception. API interception is greatly simplified using Detours. I recommend everyone to have a look at the source and the documentation of this library. Detours works by changing the first few processor instructions at the start of the actual API, to invoke the interceptor function or the Detour. The interceptor function can call the real function with actual instructions if needed. The only problem remaining was to inject some code in the devnev process. The easiest way to do that was to write a VS add-in. The add-in can use the Detours library to intercept CreateProcess calls.

The add-in

I named the add-in dbgfix. There are two solutions and two projects included with the source code. dbgfix2003.sln is for VS.NET 2003 users and dbgfix.sln is for VS.NET 2002 users.

To use the add-in directly :-

  1. Extract the source zip files.
  2. Register the add-in by calling RegSvr32 dbgfix.dll

If you choose to build the source, the add-in gets registered in the post build step. Here is what the add-in code does in brief:-

  1. In the OnConnection event the add-in uses Detours library to hook CreateProcessW and CreateProcessA APIs. This is done only if VS.NET is running under the credentials of the primary interactive user - the user who logged on to the machine from the logon screen.
  2. In the OnDisconnection event the add-in cleans up by removing the hooks on CreateProcessW and CreateProcessA APIs.

OnConnection

Lets examine the code of the OnConnection method of the add-in.

  1. Find whether VS.NET is running as primary interactive user. For each window station, system associates a user. The SID of the user can be obtained by calling GetUserObjectInformation on the window station handle of winsta0.
    //Winsta0 is associated with the primary interactive user
    
    HWINSTA hwinsta = OpenWindowStation(TEXT("winsta0"), 
                               FALSE, WINSTA_READATTRIBUTES);
    
    //Get the sid associated with winsta0
    
    DWORD dwLength = 0;
    
    if (!GetUserObjectInformation(hwinsta, UOI_USER_SID, 
                                       NULL, 0, &dwLength))
    {
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            AtlThrowLastWin32();
    }
    
    CAutoVectorPtr<BYTE> spSid(new BYTE[dwLength]);
    
    if (spSid == NULL)
        AtlThrow(E_OUTOFMEMORY);
    
    if (!GetUserObjectInformation(hwinsta, UOI_USER_SID, 
                                spSid, dwLength, &dwLength))
        AtlThrowLastWin32();
  2. The next step is to find the logon sid of the user who launched devenv. This can be obtained from the process token.
    //Get the sid associated with the process token
    
    CAccessToken token;
    
    if (!token.GetProcessToken(TOKEN_QUERY))
        AtlThrowLastWin32();
    
    CSid sidLogon;
    
    if (!token.GetLogonSid(&sidLogon))
        AtlThrowLastWin32();
    
    m_bRunningAsPrimary = (sidLogon == *(SID*)((BYTE*)spSid));
  3. Finally if the logon sid of the user is different from the sid associated with the user of winsta0, we call into Detours library.
    if (!m_bRunningAsPrimary)
    {
        //This means that devnv is running in a different user 
    
        //account than the primary interactive user
    
        DetourFunctionWithTrampoline((PBYTE)Real_CreateProcessW, 
                                      (PBYTE)CreateProcessW_Detour);
        DetourFunctionWithTrampoline((PBYTE)Real_CreateProcessA, 
                                      (PBYTE)CreateProcessA_Detour);
    }

    The first DetourFunctionWithTrampoline call modifies the first few instructions at the address of the CreateProcessWand invoke the function CreateProcessW_Detour. The actual CreateProcess function can still be called using the Real_CreateProcessW. For a complete discussion on how Detours work, refer the Detour web site. Here is how the CreateProcessW_Detour function looks like.

    BOOL WINAPI CreateProcessW_Detour(LPCWSTR lpApplicationName, 
       LPWSTR  lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, 
       LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles, 
       DWORD dwCreationFlags, LPVOID lpEnvironment, 
       LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, 
       LPPROCESS_INFORMATION lpProcessInformation)
    {
       if (lpStartupInfo->lpDesktop != NULL)
       {
           //Check for empty string
    
           if (*lpStartupInfo->lpDesktop == 0)
               lpStartupInfo->lpDesktop = NULL;
       }
    
       return Real_CreateProcessW(lpApplicationName, lpCommandLine, 
              lpProcessAttributes, lpThreadAttributes, 
              bInheritHandles, dwCreationFlags, 
              lpEnvironment, lpCurrentDirectory, 
              lpStartupInfo, lpProcessInformation);
    }

    Basically if the lpDesktop is an empty string, it is converted to NULL before calling the real CreateProcessW. This makes the invoked process to inherit the same window station as VS.NET, essentially fixing the problem.

Conclusion

This simple add-in resolves the problem with launching of IE. Thanks to Microsoft research for providing the source of Detours library. Please note that only detours.lib and detours.h is included with the source of this article. If you are interested in the full source of Detours, you can download it from the Detours web site.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralCan you help me with Detours intercepting a COM method?
ehaerim
9:17 16 Oct '07  
I've been very much enjoying the Detours concept and experimenting with it to see what I can do with Detours.

I've been reading the Detours.chm help document, and also trying to understand the samples included in the Detours Express 2.1 package. A few I could easily understand how it works, but some I am at a loss.

For example, the doc says 'commem' sample Demostrates how to detour a member function of a COM interface.

This is exactly what I would like to know at this moment. But the sample is a little different from what I want and don't know how to suit my needs.

Here is what I want to do.

T.exe : An EXE COM server program. It loads a plugin COM DLL called P.dll.
P.dll : A COM DLL server program supporting a coclass object called CNeedToBeDetoured having CLSID_NeedToBeDetoured as its class id. This coclass provides an interface IID_INeedToBeDetoured. And
IID_INeedToBeDetoured has a method INeedToBeDetoured::DetourMe().

When T.exe runs, it searches/loads P.dll to CoCreateInstance an object with CLSID_NeedToBeDetoured.
And T.exe calls INeedToBeDetoured::DetourMe method.

I need to intercept the DetourMe method before it gets called for the first time and do some preprocessing.

I tried to modify the 'commem' sample for this purpose, but it is far beyond my ability.

I love the Detours library so much and got excited when I first found it. But now, I am a bit frustrated trying the above thing.

Please help me with this. There was no one I could ask for help on this matter at all.

If possible, please write me a working sample or send me one if you have already satisfying what I've described above.

You can send me email at ehaerim@gmail.com. Or I am reachable at MSN messenger with id "haerim@investware.net".


Best Regards,

HaeRim Lee

GeneralIt works! (nearly)
napisan2002
12:43 2 Aug '05  
Thank you so much for your idea.
It basically works, but since I use the MakeMeAdmin stuff, my admin user to launch VS is my actual logon user.
So the SIDs are the same, and I had to modify a little bit the add-it.
After that, it works like a charm
Thanks
Stefano
GeneralDoes it work?
clau3107
14:05 30 Nov '04  
Breaking News / Update: with the explanations in the article, I downloaded the latest detours lib and compiled it. (I had to do minor modifications to the makefiles but it worked).

Then, I started an Add-In project from scratch, adding the code as explained in the article.

Again, with some minor modifications and testing, it worked!! Problem solved! (wherever you are) thanks Rama Krishna vavilala for sharing the theory and your solution!!

Claudio Pacciarini

------------------------------------

I'm trying to develop ASP.NET apps while logged in as a non admin account.
I do this:

1) I log as a non admin user.

2) I open a CMD.EXE as an admin, using something like:
runas /user:MyDomain\MyLocalAdmin cmd.exe

3) I start visual studio, typing: devenv

4) I create an ASP.NET web app and then press F5 to run and debug it. Problem is, Internet Explorer runs but its window is not visible. I can see iexplore.exe running in the task manager process list though. It's probably running in a different window station.

When I found this project, I thought: This should solve my problem!
But I had no luck yet.

After I read the article, downloaded and extracted the sources, I found no solutions (no *.sln files) as supposedly, mentioned in the article. Two solution files, dbgfix2003.sln (for VS.NET 2003 users) and dbgfix.sln for previous versions of VS.NET should be included, but no, those are not there.

Anyway, I decided to try the precompiled add-in, installing it using regsvc32. Then I launched VS.NET 2003. I went to the VS.NET 2003 Add-In manager (Tools->Add-In Manager...) and enabled the plug-in. Trying again, no luck, nothing happened.

I tried also running MakeMeAdmin.cmd, same story. Does anybody got this working? Can you share how?

Many thanks.

Claudio Pacciarini
GeneralRe: Detours is _NOT_ for commercial use...
Rama Krishna
6:20 11 Dec '03  
Yes that is true. I am not using it for commercial purposes. You are not asked to pay anything to download. Infact the detour source is also not included because the license agreement alows only for distribution of the dll and the lib file.


Somewhere in the world there is a machine language programmer waiting for that damned assembly language fad to pass. - Stan Shanon
GeneralIE Still Invisible Problem
SteveC88
10:43 13 Oct '03  
0.
Running Win XP-Pro with all SPs, etc. Logged on locally with my non-admin user account.

1.
I created a new local account, member of Users local group.

2.
I set the user name/password in machine.config to this account.

3.
I extracted your DLL, copied to to a local location, and regsvr32'd it successfully.

4.
I set the User Rights for this new local account (via Local Security Policy MMC):
Access this Computer from the Network
Increase Scheduling Priority
Log on as a Batch Job
Log on as a Service
Log on Locally

5.
Reboot for good measure.

6.
I launch VS.NET 2003 with RunAs so it will operate under the new local account.

7.
I open an ASP.NET web project.

8.
I press [F5], and.... the IE session is still invisible.


What else must be done?

Thanks.


Generalerrors ,
Stoney Tian
18:23 27 Jun '03  
c:\Documents and Settings\Administrator\桌面\dbgfix\stdafx.h(46): error C3506: 没有为 LIBID“{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}”注册的类型库

c:\Documents and Settings\Administrator\桌面\dbgfix\stdafx.h(46): fatal error C1104: 导入 libid 时遇到致命错误:“AC0714F2-3D04-11D1-AE7D-00A0C90F26F4”
i am in china , so above is error message some of in chinese.


My Homepage : http://www.accesine.com


Last Updated 17 Apr 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010