LPLOCALGROUP_MEMBERS_INFO_1 pstMembersInfo = 0;
DWORD entriesread = 0;
DWORD totalentries = 0;
if( 0 != NetLocalGroupGetMembers( NULL, _T("Administrators"), 1, (LPBYTE*)
&pstMembersInfo,MAX_PREFERRED_LENGTH,
&entriesread, &totalentries, 0 ))
{
AfxMessageBox( _T("NetLocalGroupGetMembers failed !"));
return ;
}
for( DWORD dwIdx =0; dwIdx < entriesread; dwIdx ++ )
{
AfxMessageBox( pstMembersInfo[dwIdx].lgrmi1_name );
}
NetApiBufferFree( pstMembersInfo );
Saturday, December 20, 2008
Function to get the local system Administrator Name
Monday, October 27, 2008
How to find whether the parent process is GUI or Console
if( AttachConsole( ATTACH_PARENT_PROCESS ))
{
AfxMessageBox( _T("Parent process is a console application"));
}
else
{
AfxMessageBox( _T("Parent process is not a console application"));
}
Tuesday, August 26, 2008
new with empty bracket
int *pnValue = new int[];
One of my friend asked me what will happen if the above statement is executed. Executed ??? I though the code won't even compile. Surprisingly it compile and even returned a pointer. Wow that was some thing unbelievable.
OK now the question is, what will be size of memory that pnValue points?
The two API's in windows that allocates and de allocates the memeory are HeapAlloc and HeepFree. The CRT functions malloc and free are actually wrappers the above API. The new, new[], delete, delete[] are again another wrapper around the malloc and free. So when ever you allocates some memory using new or new[], it will finally reach the HeapAlloc function. This function is defined as
LPVOID WINAPI HeapAlloc(
__in HANDLE hHeap,
__in DWORD dwFlags,
__in SIZE_T dwBytes
);
From the above definition, you can see that the third parameter to this function is the number of BYTES to be allocated . So to find out what "new int[]" returns, we can put a break point in the entry point of HeapAlloc and check the value of dwBytes( in dis assembly ).
when I tried, the dwBytes turned out be 1 !!! This one byte cannot even hold one int variable. That means any further operation using such a pointer will possibly crash.
Another interesting thing is "int *pnValue = new int[0];" also returns a pointer pointing a memory of 1 byte long.
Wednesday, August 20, 2008
How to open Popup Blocker Settings window of IE programmatically
Well it is with the help of "DisplayPopupWindowManagementDialog" function in the "C:\WINDOWS\system32\inetcpl.cpl".
This question was asked by some one in the codeproject and at that time I was also unaware of any function for this. How ever I felt it interesting so just decided to have a try.
It told me that "USER32.dll" has created the dialog. Liar... I was much sure that user32.dll isn't the real dll behind it. So this technique to find the dll didn't really work. So I had to find another way...
Every window has a thread associated with it. If you have the window handle, you can easily retirive the thread Id associated with it using the GetWindowThreadProcessId function. Any way I am not going to code for this. Tools like spy++, WinID displays the thread id of the window if we select a window using it. So the Thread ID displayed in Spy++ was 0xB94( 2964 in decimal ).
If we took the properties of a process in the process explorer, it will list all the threads in the process and each thread's call stack. So the thing next to do is to select the iexplorer process, select the thread with ID 2964 and took its call stack.
And in the call stack, there was only one un familiar dll and function the "inetcpl.cpl" and the DisplayPopupWindowManagementDialog function in it. So I found out the "inetcpl.cpl" file in the system32 folder and when double clicked on it, huiii it shows the "internet options" dialog.
The control panel files (.cpl ), are just a dll with a some special export functions( If you want to know more about control panel files I suggest you to read Paul DiLascia's Q&A[^] article ). With the dependency walker, I confirmed the presence of DisplayPopupWindowManagementDialog in it. But to call this function, I need to the find how it is declared, what all are the arguments etc. Fortunately some else has already document the function proto and with a google search, I was able to find it out. Happy ending!!!!
And ho ya here is the sample code..
typedef BOOL (WINAPI *DisplayPopupWindowP)( HANDLE hWnd, LPCTSTR lpCaption );
void CDialogBasedDlg::OnBnClickedButton1()
{
HMODULE hModule = LoadLibrary( _T("inetcpl.cpl") );
DisplayPopupWindowP DisplayPopupWindowManagementDialog =
( DisplayPopupWindowP)GetProcAddress(hModule,
"DisplayPopupWindowManagementDialog" );
if( !DisplayPopupWindowManagementDialog )
{
return;//error
}
DisplayPopupWindowManagementDialog( m_hWnd,
_T("www.Sitetounblock.com"));
}
Sunday, August 17, 2008
GetFinalPathNameByHandle API Hungs
Some months back, I have written a small utility OpenedFileFinder which list all the file that are opened under a certain folder. While writing this application,the main problem I came across was to get the file name from the handle. Initially I used a function called NtQueryObject(). But the problem with this API is that if we try to query the details for certain object such as pipes, directory handles etc, it will hangs. So in my application finally I have to introduce a driver to get round of this hanging problem. When I found the new GetFinalPathNameByHandle(), I was so happy and I thought at least I can avoid the driver in the vista. So I had a try on this API. But I came to find that this API also have the same hanging problem which I described earlier.
It seems the GetFinalPathNameByHandle is also using the same NtQueryObject() to get the file name and so it hangs. Any how, I have reported this bug to the microsoft connect. Let us see how they solve the problem.
Another API, that worth mentioning here is GetFileInformationByHandleEx(), which is also a new API introduced in Vista. Using this API also, I can get the file name from a handle. So I decided to check whether the same problem exists in this API also. Surprisingly it worked fine. And in MSDN also it is mentioned that it uses a driver for attaining the task. So I highly suggest every one to use GetFileInformationByHandleEx() API instead of GetFinalPathNameByHandle().
Thursday, June 19, 2008
How Local Static Variable Is Implemented in vc++
OK let start with the storage of the static variables. Where do you think a static variable declared inside a function is stored? If your answer is on the stack, you are wrong. All static and global variables are stored in a section called ".data" in the exe. For example check the below code.
int g_GlobalVariable = 0x10;
static int nValue1 = 0x11;
void main()
{
static int nValue2 = 0x12;
// Take the address
int *pglobal = &g_GlobalVariable;
int *pValue1 = &nValue1;
int *pValue2 = &nValue2;
}
You can see that the "nValue2" variable is initialized at the compile time itself. so no instruction is generated by the compiler for a statement like static int nValue2 = 0x12;
So compiler did a nice job by setting the value to variable at the compile time itself. But that was a C type object. What if we declare a static C++ object inside a function. This time the compiler cannot initialize the variable at the compile time because the constructor need to be invoked to initialize a C++ object. Consider the below code
class TestClass
{
public:
TestClass()
{
m_nMemeberVar = 10;
}
int m_nMemeberVar;
};
TestClass& AFunction()
{
static TestClass cppObject;
return cppObject;
}
In the above code, the AFunction() function creates a static object of class TestClass and as you know the cppObject will be initialized only once. How does the compiler manages to do it? Well answer is compiler keeps a flag!!! I.e when the compiler sees a c++, static object is declared inside a function, it will create a global byte variable with value 0 and some addition instruction such that the constructor of the object will be called only if the value of the byte variable is 0 and it also set the value of the byte variable as 1. So from the next time onwards, the constructor will not be called. Below is the dis assembly for the statement static TestClass cppObject.
static TestClass cppObject;
// Zero out the eax register
00401E79 xor eax,eax
// Copy the flag variable to al register
00401E7B mov al,[`AFunction'::`2'::$S230 (00408104)]
00401E80 and eax,1
// Check eax equal to zero
00401E83 test eax,eax
// If it is not zero, go to end.
00401E85 jne AFunction+3Dh (00401ead)
// Copy the flag variable to the cl register
00401E87 mov cl,byte ptr [`AFunction'::`2'::$S230 (00408104)]
// cl = 1
00401E8D or cl,1
// Copy back the content of cl register to the flag variable
00401E90 mov byte ptr [`AFunction'::`2'::$S230 (00408104)],cl
// Call the constructor of cppObject
00401E96 mov ecx,offset theApp+0C8h (00408100)
00401E9B call TestClass::TestClass (00401ec0)
Monday, May 5, 2008
Optimizing Storage for Constant Data
const char* g_pchar = "this is a string";
You might be knowing that if we run multiple copies of a exe or dll, the code portion is not duplicated per process. So do the constant data. This is because the constant datas are stored in a special section of exe called ".rdata"( The code protion is stored in the ".text" section ). But guess what will happen if we have declaration like..
const CString g_str("this is the worst thing I can do");
Now you've got the CString object (which is quite small) in the .bss section( .bss section stores nonconstant uninitialized data ), and you've also got a character array in the .data section( Nonconstant initialized data ), neither of which can be backed by the EXE file. To make matters worse, when the program starts, the CString class must allocate heap memory for a copy of the characters. You would be much better off using a const character array instead of a CString object. So never ever declare like that ( Reference "Programming Microsoft vc++" by David Kruglinski ).
OK that was the theory. Now the reason why I stated the above theory is that, last week, I installed the latest VS 2008 feature pack. This feature pack had some new classes for MFC. So I decided to check out the new classes. The CWinAppEx is on among them. On the very first function I stepped in( constructor of the CWinAppEx ), I found the following piece of code..
const CString strRegEntryNameWorkspace = _T("Workspace");
m_strRegSection = strRegEntryNameWorkspace;
ops . And when I scrolled up, there was another bunch of similar codes
static const CString strWindowPlacementRegSection = _T("WindowPlacement");
static const CString strRectMainKey = _T("MainWindowRect");
static const CString strFlagsKey = _T("Flags");
static const CString strShowCmdKey = _T("ShowCmd");
static const CString strRegEntryNameSizingBars = _T("\\SizingBars");
static const CString strRegEntryVersion = _T("ControlBarVersion");
static const CString strVersionMajorKey = _T("Major");
static const CString strVersionMinorKey = _T("Minor");
I dont think any one has seen such a badly written, poor quality code in the old MFC 4 code. Never did I. If MFC starts like this, where will the developers using MFC ends?
When I discussed about this in code project and MSDN forum, I got some interesting response. That's how I came to here about Wirth's law[^] , which states
Software gets slower, faster than hardware gets faster.
or
Software is decelerating faster than hardware is accelerating.
Very true and you just saw one example.
Monday, April 21, 2008
Loader snaps
Normally if we start an application from the debugger in the debugging mode, the output window shows some messages as shown below.
Loaded 'c:\WINDOWS\system32\calc.exe', no matching symbolic information found.
Loaded 'ntdll.dll', no matching symbolic information found.
Loaded 'C:\WINDOWS\system32\kernel32.dll', no matching symbolic information found.
Loaded 'C:\WINDOWS\system32\shell32.dll', no matching symbolic information found.
Loaded 'C:\WINDOWS\system32\advapi32.dll', no matching symbolic information found.
Loaded 'C:\WINDOWS\system32\rpcrt4.dll', no matching symbolic information found.
Loaded 'C:\WINDOWS\system32\secur32.dll', no matching symbolic information found.
Below is the loader snaps of calc.exe after setting the flag.
Loaded 'c:\WINDOWS\system32\calc.exe', no matching symbolic information found. Loaded 'ntdll.dll', no matching symbolic information found.
Loaded 'C:\WINDOWS\system32\kernel32.dll', no matching symbolic information found.
LDR: LdrLoadDll, loading ShimEng.dll from
LDR: Loading (DYNAMIC, NON_REDIRECTED) c:\WINDOWS\system32\ShimEng.dll
Loaded 'C:\WINDOWS\system32\shimeng.dll', no matching symbolic information found.
LDR: ShimEng.dll bound to ntdll.dll
LDR: ShimEng.dll has correct binding to ntdll.dll
LDR: ShimEng.dll bound to KERNEL32.dll
LDR: ShimEng.dll has stale binding to KERNEL32.dll
LDR: Stale Bind KERNEL32.dll from ShimEng.dll
LDR: LdrGetProcedureAddress by NAME - SE_InstallBeforeInit
LDR: LdrGetProcedureAddress by NAME - SE_InstallAfterInit
LDR: LdrGetProcedureAddress by NAME - SE_DllLoaded
LDR: LdrGetProcedureAddress by NAME - SE_DllUnloaded
LDR: LdrGetProcedureAddress by NAME - SE_GetProcAddress
LDR: LdrGetProcedureAddress by NAME - SE_ProcessDying
LDR: LdrGetDllHandle, searching for ShimEng.dll from
LDR: LdrGetDllHandle, searching for C:\WINDOWS\AppPatch\AcGenral.DLL from
LDR: LdrLoadDll, loading C:\WINDOWS\AppPatch\AcGenral.DLL from
LDR: Loading (DYNAMIC, NON_REDIRECTED) C:\WINDOWS\AppPatch\AcGenral.DLL
Loaded 'C:\WINDOWS\AppPatch\AcGenral.dll', no matching symbolic information found.
LDR: AcGenral.DLL bound to ntdll.dll
LDR: AcGenral.DLL has correct binding to ntdll.dll
LDR: AcGenral.DLL bound to KERNEL32.dll
LDR: AcGenral.DLL has stale binding to KERNEL32.dll
LDR: AcGenral.DLL bound to ntdll.dll via forwarder(s) from kernel32.dll
LDR: AcGenral.DLL has correct binding to ntdll.dll
LDR: Stale Bind KERNEL32.dll from AcGenral.DLL
LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlSizeHeap
LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap
LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap
LDR: LdrGetProcedureAddress by NAME - RtlReAllocateHeap
LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection
LDR: AcGenral.DLL bound to USER32.dll
LDR: AcGenral.DLL has stale binding to USER32.dll
LDR: Stale Bind USER32.dll from AcGenral.DLL
LDR: AcGenral.DLL bound to GDI32.dll
LDR: AcGenral.DLL has stale binding to GDI32.dll
LDR: Stale Bind GDI32.dll from AcGenral.DLL
LDR: AcGenral.DLL bound to ADVAPI32.dll
LDR: AcGenral.DLL has correct binding to ADVAPI32.dll
LDR: AcGenral.DLL bound to WINMM.dll
LDR: Loading (STATIC, NON_REDIRECTED) c:\WINDOWS\system32\WINMM.dll
Loaded 'C:\WINDOWS\system32\winmm.dll', no matching symbolic information found.
LDR: WINMM.dll bound to ntdll.dll
LDR: WINMM.dll has correct binding to ntdll.dll
LDR: WINMM.dll bound to USER32.dll
LDR: WINMM.dll has stale binding to USER32.dll
LDR: Stale Bind USER32.dll from WINMM.dll
LDR: WINMM.dll bound to GDI32.dll
LDR: WINMM.dll has stale binding to GDI32.dll
LDR: Stale Bind GDI32.dll from WINMM.dll
LDR: WINMM.dll bound to KERNEL32.dll
LDR: WINMM.dll has stale binding to KERNEL32.dll
LDR: WINMM.dll bound to ntdll.dll via forwarder(s) from kernel32.dll
LDR: WINMM.dll has correct binding to ntdll.dll
LDR: Stale Bind KERNEL32.dll from WINMM.dll
LDR: LdrGetProcedureAddress by NAME - RtlReAllocateHeap
LDR: LdrGetProcedureAddress by NAME - RtlSizeHeap
LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap
LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection
LDR: WINMM.dll bound to ADVAPI32.dll
LDR: WINMM.dll has correct binding to ADVAPI32.dll
LDR: WINMM.dll bound to RPCRT4.dll
LDR: WINMM.dll has stale binding to RPCRT4.dll
LDR: Stale Bind RPCRT4.dll from WINMM.dll
LDR: AcGenral.DLL has correct binding to WINMM.dll
LDR: AcGenral.DLL bound to ole32.dll
Loaded 'C:\WINDOWS\system32\ole32.dll', no matching symbolic information found.
LDR: ADVAPI32.dll used by ole32.dll
LDR: Snapping imports for ole32.dll from ADVAPI32.dll
LDR: GDI32.dll used by ole32.dll
LDR: Snapping imports for ole32.dll from GDI32.dll
LDR: KERNEL32.dll used by ole32.dll
LDR: Snapping imports for ole32.dll from KERNEL32.dll
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap
LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap
LDR: LdrGetProcedureAddress by NAME - RtlSizeHeap
LDR: LdrGetProcedureAddress by NAME - RtlReAllocateHeap
LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection
LDR: msvcrt.dll used by ole32.dll
LDR: Snapping imports for ole32.dll from msvcrt.dll
LDR: ntdll.dll used by ole32.dll
LDR: Snapping imports for ole32.dll from ntdll.dll
LDR: RPCRT4.dll used by ole32.dll
LDR: Snapping imports for ole32.dll from RPCRT4.dll
LDR: USER32.dll used by ole32.dll
LDR: Snapping imports for ole32.dll from USER32.dll
LDR: AcGenral.DLL has stale binding to ole32.dll
LDR: Stale Bind ole32.dll from AcGenral.DLL
LDR: AcGenral.DLL bound to OLEAUT32.dll
Loaded 'C:\WINDOWS\system32\oleaut32.dll', no matching symbolic information found.
LDR: ADVAPI32.dll used by OLEAUT32.dll
LDR: Snapping imports for OLEAUT32.dll from ADVAPI32.dll
LDR: GDI32.dll used by OLEAUT32.dll
LDR: Snapping imports for OLEAUT32.dll from GDI32.dll
LDR: KERNEL32.dll used by OLEAUT32.dll
LDR: Snapping imports for OLEAUT32.dll from KERNEL32.dll
LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap
LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap
LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection
LDR: msvcrt.dll used by OLEAUT32.dll
LDR: Snapping imports for OLEAUT32.dll from msvcrt.dll
LDR: ole32.dll used by OLEAUT32.dll
LDR: Snapping imports for OLEAUT32.dll from ole32.dll
LDR: RPCRT4.dll used by OLEAUT32.dll
LDR: Snapping imports for OLEAUT32.dll from RPCRT4.dll
LDR: USER32.dll used by OLEAUT32.dll
LDR: Snapping imports for OLEAUT32.dll from USER32.dll
LDR: AcGenral.DLL has stale binding to OLEAUT32.dll
LDR: Stale Bind OLEAUT32.dll from AcGenral.DLL
LDR: AcGenral.DLL bound to MSACM32.dll
LDR: Loading (STATIC, NON_REDIRECTED) c:\WINDOWS\system32\MSACM32.dll
Loaded 'C:\WINDOWS\system32\msacm32.dll', no matching symbolic information found.
LDR: MSACM32.dll bound to msvcrt.dll
LDR: MSACM32.dll has stale binding to msvcrt.dll
LDR: Stale Bind msvcrt.dll from MSACM32.dll
LDR: MSACM32.dll bound to ntdll.dll
LDR: MSACM32.dll has correct binding to ntdll.dll
LDR: MSACM32.dll bound to USER32.dll
LDR: MSACM32.dll has stale binding to USER32.dll
LDR: Stale Bind USER32.dll from MSACM32.dll
LDR: MSACM32.dll bound to GDI32.dll
LDR: MSACM32.dll has stale binding to GDI32.dll
LDR: Stale Bind GDI32.dll from MSACM32.dll
LDR: MSACM32.dll bound to KERNEL32.dll
LDR: MSACM32.dll has stale binding to KERNEL32.dll
LDR: MSACM32.dll bound to ntdll.dll via forwarder(s) from kernel32.dll
LDR: MSACM32.dll has correct binding to ntdll.dll
LDR: Stale Bind KERNEL32.dll from MSACM32.dll
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection
LDR: MSACM32.dll bound to ADVAPI32.dll
LDR: MSACM32.dll has correct binding to ADVAPI32.dll
LDR: MSACM32.dll bound to WINMM.dll
LDR: MSACM32.dll has correct binding to WINMM.dll
LDR: AcGenral.DLL has correct binding to MSACM32.dll
LDR: AcGenral.DLL bound to VERSION.dll
Loaded 'C:\WINDOWS\system32\version.dll', no matching symbolic information found.
LDR: VERSION.dll bound to KERNEL32.dll
LDR: VERSION.dll has stale binding to KERNEL32.dll
LDR: VERSION.dll bound to NTDLL.DLL via forwarder(s) from kernel32.dll
LDR: VERSION.dll has correct binding to NTDLL.DLL
LDR: Stale Bind KERNEL32.dll from VERSION.dll
LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: VERSION.dll bound to NTDLL.DLL
LDR: VERSION.dll has correct binding to NTDLL.DLL
LDR: AcGenral.DLL has correct binding to VERSION.dll
LDR: AcGenral.DLL bound to SHELL32.dll
LDR: AcGenral.DLL has stale binding to SHELL32.dll
LDR: Stale Bind SHELL32.dll from AcGenral.DLL
LDR: AcGenral.DLL bound to SHLWAPI.dll
LDR: AcGenral.DLL has stale binding to SHLWAPI.dll
LDR: Stale Bind SHLWAPI.dll from AcGenral.DLL
LDR: AcGenral.DLL bound to USERENV.dll
Loaded 'C:\WINDOWS\system32\userenv.dll', no matching symbolic information found.
LDR: USERENV.dll bound to msvcrt.dll
LDR: USERENV.dll has stale binding to msvcrt.dll
LDR: Stale Bind msvcrt.dll from USERENV.dll
LDR: USERENV.dll bound to ntdll.dll
LDR: USERENV.dll has correct binding to ntdll.dll
LDR: USERENV.dll bound to ADVAPI32.dll
LDR: USERENV.dll has correct binding to ADVAPI32.dll
LDR: USERENV.dll bound to KERNEL32.dll
LDR: USERENV.dll has stale binding to KERNEL32.dll
LDR: USERENV.dll bound to ntdll.dll via forwarder(s) from kernel32.dll
LDR: USERENV.dll has correct binding to ntdll.dll
LDR: Stale Bind KERNEL32.dll from USERENV.dll
LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error
LDR: USERENV.dll bound to RPCRT4.dll
LDR: USERENV.dll has stale binding to RPCRT4.dll
LDR: Stale Bind RPCRT4.dll from USERENV.dll
LDR: USERENV.dll bound to USER32.dll
LDR: USERENV.dll has stale binding to USER32.dll
LDR: Stale Bind USER32.dll from USERENV.dll
LDR: AcGenral.DLL has correct binding to USERENV.dll
LDR: AcGenral.DLL bound to UxTheme.dll
LDR: Loading (STATIC, NON_REDIRECTED) c:\WINDOWS\system32\UxTheme.dll
Loaded 'C:\WINDOWS\system32\uxtheme.dll', no matching symbolic information found.
LDR: UxTheme.dll bound to msvcrt.dll
LDR: UxTheme.dll has stale binding to msvcrt.dll
LDR: Stale Bind msvcrt.dll from UxTheme.dll
LDR: UxTheme.dll bound to ntdll.dll
LDR: UxTheme.dll has correct binding to ntdll.dll
LDR: UxTheme.dll bound to KERNEL32.dll
LDR: UxTheme.dll has stale binding to KERNEL32.dll
LDR: UxTheme.dll bound to ntdll.dll via forwarder(s) from kernel32.dll
LDR: UxTheme.dll has correct binding to ntdll.dll
LDR: Stale Bind KERNEL32.dll from UxTheme.dll
LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlDeleteCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection
LDR: UxTheme.dll bound to USER32.dll
LDR: UxTheme.dll has stale binding to USER32.dll
LDR: Stale Bind USER32.dll from UxTheme.dll
LDR: UxTheme.dll bound to GDI32.dll
LDR: UxTheme.dll has stale binding to GDI32.dll
LDR: Stale Bind GDI32.dll from UxTheme.dll
LDR: UxTheme.dll bound to ADVAPI32.dll
LDR: UxTheme.dll has correct binding to ADVAPI32.dll
LDR: AcGenral.DLL has correct binding to UxTheme.dll
LDR: Refcount WINMM.dll (1)
LDR: Refcount ole32.dll (1)
LDR: Refcount OLEAUT32.dll (1)
LDR: Refcount ole32.dll (2)
LDR: Refcount MSACM32.dll (1)
LDR: Refcount WINMM.dll (2)
LDR: Refcount VERSION.dll (1)
LDR: Refcount USERENV.dll (1)
LDR: Refcount UxTheme.dll (1)
[1cb0,1cac] LDR: Real INIT LIST for process c:\WINDOWS\system32\calc.exe pid 7344 0x1cb0
[1cb0,1cac] C:\WINDOWS\AppPatch\AcGenral.DLL init routine 6F8A5E1A
[1cb0,1cac] LDR: AcGenral.DLL loaded - Calling init routine at 6F8A5E1A
LDR: LdrGetDllHandle, searching for kernel32.dll from
LDR: LdrGetProcedureAddress by NAME - InitializeCriticalSectionAndSpinCount
LDR: LdrGetProcedureAddress by NAME - GetHookAPIs
[1cb0,1cac] LDR: Real INIT LIST for process c:\WINDOWS\system32\calc.exe pid 7344 0x1cb0
[1cb0,1cac] C:\WINDOWS\system32\Secur32.dll init routine 77FE2131
[1cb0,1cac] C:\WINDOWS\system32\RPCRT4.dll init routine 77E7628F
[1cb0,1cac] C:\WINDOWS\system32\ADVAPI32.dll init routine 77DD70D4
[1cb0,1cac] C:\WINDOWS\system32\USER32.dll init routine 7E42E966
[1cb0,1cac] C:\WINDOWS\system32\GDI32.dll init routine 77F16587
[1cb0,1cac] C:\WINDOWS\system32\msvcrt.dll init routine 77C1F2A1
[1cb0,1cac] C:\WINDOWS\system32\SHLWAPI.dll init routine 77F651FB
[1cb0,1cac] C:\WINDOWS\system32\SHELL32.dll init routine 7C9E7376
[1cb0,1cac] c:\WINDOWS\system32\WINMM.dll init routine 76B42B69
[1cb0,1cac] C:\WINDOWS\system32\ole32.dll init routine 774FD0A1
[1cb0,1cac] C:\WINDOWS\system32\OLEAUT32.dll init routine 77121558
[1cb0,1cac] c:\WINDOWS\system32\MSACM32.dll init routine 77BE1292
[1cb0,1cac] C:\WINDOWS\system32\VERSION.dll init routine 77C01135
[1cb0,1cac] C:\WINDOWS\system32\USERENV.dll init routine 769C15D4
[1cb0,1cac] c:\WINDOWS\system32\UxTheme.dll init routine 5AD71626
[1cb0,1cac] LDR: Secur32.dll loaded - Calling init routine at 77FE2131
[1cb0,1cac] LDR: RPCRT4.dll loaded - Calling init routine at 77E7628F
[1cb0,1cac] LDR: ADVAPI32.dll loaded - Calling init routine at 77DD70D4
[1cb0,1cac] LDR: USER32.dll loaded - Calling init routine at 7E42E966
LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from
LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;
]LDR: LdrLoadDll, loading C:\WINDOWS\system32\IMM32.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;
]LDR: Loading (DYNAMIC, NON_REDIRECTED) C:\WINDOWS\system32\IMM32.DLL
Loaded 'C:\WINDOWS\system32\imm32.dll', no matching symbolic information found.
LDR: IMM32.DLL bound to USER32.dll
LDR: IMM32.DLL has stale binding to USER32.dll
LDR: Stale Bind USER32.dll from IMM32.DLL
LDR: IMM32.DLL bound to ntdll.dll
LDR: IMM32.DLL has correct binding to ntdll.dll
LDR: IMM32.DLL bound to KERNEL32.dll
LDR: IMM32.DLL has stale binding to KERNEL32.dll
LDR: IMM32.DLL bound to ntdll.dll via forwarder(s) from kernel32.dll
LDR: IMM32.DLL has correct binding to ntdll.dll
LDR: Stale Bind KERNEL32.dll from IMM32.DLL
LDR: LdrGetProcedureAddress by NAME - RtlGetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlSetLastWin32Error
LDR: LdrGetProcedureAddress by NAME - RtlAllocateHeap
LDR: LdrGetProcedureAddress by NAME - RtlFreeHeap
LDR: IMM32.DLL bound to GDI32.dll
LDR: IMM32.DLL has stale binding to GDI32.dll
LDR: Stale Bind GDI32.dll from IMM32.DLL
LDR: IMM32.DLL bound to ADVAPI32.dll
LDR: IMM32.DLL has correct binding to ADVAPI32.dll
[1cb0,1cac] LDR: Real INIT LIST for process c:\WINDOWS\system32\calc.exe pid 7344 0x1cb0
[1cb0,1cac] C:\WINDOWS\system32\IMM32.DLL init routine 763912C0
[1cb0,1cac] LDR: IMM32.DLL loaded - Calling init routine at 763912C0
LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from
LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;
]LDR: LdrGetProcedureAddress by NAME - ImmWINNLSEnableIME
LDR: LdrGetProcedureAddress by NAME - ImmWINNLSGetEnableStatus
LDR: LdrGetProcedureAddress by NAME - ImmSendIMEMessageExW
LDR: LdrGetProcedureAddress by NAME - ImmSendIMEMessageExA
LDR: LdrGetProcedureAddress by NAME - ImmIMPGetIMEW
LDR: LdrGetProcedureAddress by NAME - ImmIMPGetIMEA
LDR: LdrGetProcedureAddress by NAME - ImmIMPQueryIMEW
LDR: LdrGetProcedureAddress by NAME - ImmIMPQueryIMEA
LDR: LdrGetProcedureAddress by NAME - ImmIMPSetIMEW
LDR: LdrGetProcedureAddress by NAME - ImmIMPSetIMEA
LDR: LdrGetProcedureAddress by NAME - ImmAssociateContext
LDR: LdrGetProcedureAddress by NAME - ImmEscapeA
LDR: LdrGetProcedureAddress by NAME - ImmEscapeW
LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionStringA
LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionStringW
LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionWindow
LDR: LdrGetProcedureAddress by NAME - ImmGetContext
LDR: LdrGetProcedureAddress by NAME - ImmGetDefaultIMEWnd
LDR: LdrGetProcedureAddress by NAME - ImmIsIME
LDR: LdrGetProcedureAddress by NAME - ImmReleaseContext
LDR: LdrGetProcedureAddress by NAME - ImmRegisterClient
LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionFontW
LDR: LdrGetProcedureAddress by NAME - ImmGetCompositionFontA
LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionFontW
LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionFontA
LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionWindow
LDR: LdrGetProcedureAddress by NAME - ImmNotifyIME
LDR: LdrGetProcedureAddress by NAME - ImmLockIMC
LDR: LdrGetProcedureAddress by NAME - ImmUnlockIMC
LDR: LdrGetProcedureAddress by NAME - ImmLoadIME
LDR: LdrGetProcedureAddress by NAME - ImmSetOpenStatus
LDR: LdrGetProcedureAddress by NAME - ImmFreeLayout
LDR: LdrGetProcedureAddress by NAME - ImmActivateLayout
LDR: LdrGetProcedureAddress by NAME - ImmGetCandidateWindow
LDR: LdrGetProcedureAddress by NAME - ImmSetCandidateWindow
LDR: LdrGetProcedureAddress by NAME - ImmConfigureIMEW
LDR: LdrGetProcedureAddress by NAME - ImmGetConversionStatus
LDR: LdrGetProcedureAddress by NAME - ImmSetConversionStatus
LDR: LdrGetProcedureAddress by NAME - ImmSetStatusWindowPos
LDR: LdrGetProcedureAddress by NAME - ImmGetImeInfoEx
LDR: LdrGetProcedureAddress by NAME - ImmLockImeDpi
LDR: LdrGetProcedureAddress by NAME - ImmUnlockImeDpi
LDR: LdrGetProcedureAddress by NAME - ImmGetOpenStatus
LDR: LdrGetProcedureAddress by NAME - ImmSetActiveContext
LDR: LdrGetProcedureAddress by NAME - ImmTranslateMessage
LDR: LdrGetProcedureAddress by NAME - ImmLoadLayout
LDR: LdrGetProcedureAddress by NAME - ImmProcessKey
LDR: LdrGetProcedureAddress by NAME - ImmPutImeMenuItemsIntoMappedFile
LDR: LdrGetProcedureAddress by NAME - ImmGetProperty
LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionStringA
LDR: LdrGetProcedureAddress by NAME - ImmSetCompositionStringW
LDR: LdrGetProcedureAddress by NAME - ImmEnumInputContext
LDR: LdrGetProcedureAddress by NAME - ImmSystemHandler
LDR: LdrGetProcedureAddress by NAME - CtfImmTIMActivate
LDR: LdrGetProcedureAddress by NAME - CtfImmRestoreToolbarWnd
LDR: LdrGetProcedureAddress by NAME - CtfImmHideToolbarWnd
LDR: LdrGetProcedureAddress by NAME - CtfImmDispatchDefImeMessage
LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from
LDR: LdrGetDllHandle, searching for C:\WINDOWS\system32\IMM32.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;
]LDR: LdrLoadDll, loading LPK.DLL from c:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;
]LDR: Loading (DYNAMIC, NON_REDIRECTED) c:\WINDOWS\system32\LPK.DLL
Loaded 'C:\WINDOWS\system32\lpk.dll', no matching symbolic information found.
LDR: LPK.DLL bound to ntdll.dll
LDR: LPK.DLL has correct binding to ntdll.dll
LDR: LPK.DLL bound to KERNEL32.dll
LDR: LPK.DLL has stale binding to KERNEL32.dll
LDR: LPK.DLL bound to ntdll.dll via forwarder(s) from kernel32.dll
LDR: LPK.DLL has correct binding to ntdll.dll
LDR: Stale Bind KERNEL32.dll from LPK.DLL
LDR: LdrGetProcedureAddress by NAME - RtlEnterCriticalSection
LDR: LdrGetProcedureAddress by NAME - RtlLeaveCriticalSection
LDR: LPK.DLL bound to GDI32.dll
LDR: LPK.DLL has stale binding to GDI32.dll
LDR: Stale Bind GDI32.dll from LPK.DLL
LDR: LPK.DLL bound to USER32.dll
NAME - GetThemeInt
LDR: LdrGetProcedureAddress by NAME - DrawThemeBackground
LDR: LdrGetProcedureAddress by NAME - IsThemeBackgroundPartiallyTransparent
LDR: LdrGetProcedureAddress by NAME - GetThemePartSize
LDR: LdrGetProcedureAddress by NAME - GetThemeBackgroundContentRect
LDR: LdrGetProcedureAddress by NAME - DrawThemeText
LDR: LdrGetProcedureAddress by NAME - DrawThemeParentBackground
Optionally we can set the flag under the "HLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" by adding a key in the name of the exe for which you want to show Loader information and then adding the "GlobalFlag" under it.( This is the easiest way because you needn't to restart your machine in this case. )
Here I mentioned only one value that can be set to the "GlobalFlag". To see the other possible values see GlobalFlags for Windows .
Thursday, April 17, 2008
Pointer pointing to Stack or Heap ??
Well windows dosen't provide an API or a straight forward way to acomplish this. Any how we can find a pointer points to stack or heap by simple computations and ofcourse with the help of TIB( Thread Infomation Block - If you want to learn more about TIB, have a look to the Under The Hood article of Matt Pietrek ). In the Thread information block, there are two members, the "StackTop"( located at FS[4] ) and "StackBase" ( located at FS[8] ). The "StackTop" is the memory from which the stack started, and the "StackBase" is the stack location the program commits upto that point. So any object created on stack will have an address between this two pointers. So if we get a pointer just check whether the pointer falls between the above two memory locations. if it does, then it can be consider a pointer to some stack object. So here is my API to find whether the pointer points to stack or heap.
{
LPVOID dwStackTop = 0;
LPVOID dwStackLowCurrent = 0;
__asm
{
mov EAX, FS:[4]
mov dwStackTop, eax
mov EAX, FS:[8]
mov dwStackLowCurrent, eax
}
if( pVoid <= dwStackTop && pVoid >= dwStackLowCurrent )
{
return true;
}
return false;
}
void main()
{
int OnStack;
bool bOnStack = IsMemoryOnStack( &OnStack );// Returns true
int *pOnHeap = new int;
bOnStack = IsMemoryOnStack( pOnHeap );// Returns false
}
Wednesday, April 16, 2008
Break application on dll Load
Now if you start the application from the debugger. The debugeer will report a breakpoint hit during startup. This break point will be just above the call to Dll entry point of foo.dll.( The entry point is_DllMainCRTStartup if the dll is written using vc++. This function later calls DllMain())
Tuesday, April 15, 2008
__asm int 3 in template function ( in VC6 )
template<>class T>> int Testfunc( T Obj )
{
__asm int 3;
return Obj++;
}
void main()
{
Testfunc( 1 );
};
The above code will never get compiled in vc6. It will generate the below error
"fatal error C1001: INTERNAL COMPILER ERROR
(compiler file 'msc1.cpp', line 1794)
Please choose the Technical Support command on the Visual C++ Help menu, or open the Technical Support help file for more information
Generating Code...Command line warning D4028 : minimal rebuild failure, reverting to normal build
Error executing cl.exe."
But the same code will compile fine in later versions of visual studio. Seems they have fixed the bug :)
Monday, April 14, 2008
MessageBox in ExitInstance
int CMyApp::ExitInstance()
{
AfxMessageBox( "Some message from CMyApp::ExitInstance" );
return CWinApp::ExitInstance();
}
int CMyApp::ExitInstance()
{
MSG stMsg;
while( GetMessage( &stMsg,0,0,0));
AfxMessageBox( "Some message from CMyApp::ExitInstance" );
return CWinApp::ExitInstance();
}
If you check the CWnd::OnNcDestroy() function, you can find that, it calls the AfxPostQuitMessage upon checking various conditions such as The window closed now is a Main Window, The Current instance is not a dll etc..
Monday, April 7, 2008
When a MessageBox in InitInstance didn't show..
BOOL CMyApp::InitInstance()
{
AfxEnableControlContainer();
#ifdef _AFXDLL
Enable3dControls();
#else
Enable3dControlsStatic();
#endif
HANDLE hMutex = CreateMutex( 0, 0, _T("Some_Mutex"));
if( GetLastError() == ERROR_ALREADY_EXISTS )
{
AfxMessageBox( _T("Only one instance of the application can be run"));
CloseHandle( hMutex );
return FALSE;
}
CMyDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
CloseHandle( hMutex );
return FALSE;
}
So to conclude, what I learned because of message box problem are.
1. Whether or not you are using Manifest file, you should call InitCommonControls() or InitCommonControlsEx().
2. MFC42.dll have set COMCTL32.DLL to delay load. ( But when I checked in MFC8.dll, the delayed loading of COMCTL32 is removed )
3. If we use manifest file, COMCTL32.DLL will doing the registration of all System Classes instead of user32.dll. So it is necessary to ensure that COMCTL32.DLL have loaded before you create a window belonging to system class.
Sunday, March 23, 2008
Find which dll / exe created a window.
When ever we create a window, we have to pass the an HINSTANCE into it. And later we can use GetWindowLong to get that HINSTANCE. Actually the HINSTANCE is noting but the HMODULE itself. So if we get the hinstance of a window, we can pass this handle to the
GetModuleFileNameEx() and simply get the name of the window from other processes also.
CString MyGetWindowModuleFileName( HANDLE hwindowhandle )
{
CString csModuleName;
DWORD dwProcessId;
GetWindowThreadProcessId( hwindowhandle, &dwProcessId );
HINSTANCEhModule = (HINSTANCE)GetWindowLong( hwindowhandle, GWL_HINSTANCE );
if(hModule == NULL)
{
return csModuleName;
}
HANDLE hProcess = OpenProcess(PROCESS_VM_READPROCESS_QUERY_INFORMATION, FALSE, dwProcessId );
if( hProcess == NULL )
{
return csModuleName;
}
BOOL bReturn = GetModuleFileNameEx( hProcess, hModule, csModuleName.GetBuffer( MAX_PATH), MAX_PATH );
csModuleName.ReleaseBuffer();
CloseHandle(hProcess);
return csModuleName;
}
Thursday, January 3, 2008
WM_DEVICECHANGE problem
After some investigations we found that if we make the window a top-level window (HWND_TOPMOST), there is no such problems. But what’s the relation between the z-order and the above problem. Later we got few more points to identify the relation.
1. The WM_DEVICECHANGE is send to all the top-level windows according to their z-order. That is the window at the top most position receives the message first, then only the window below it and so one.
Now everything became clear to us, some window whose z-order is greater than our application window might have hung or didn’t process the message within 20 seconds. Thus our window didn’t get a chance. Also when we made our window top level it will be one of the first window's to get WM_DEVICECHANGE message so reducing the number of windows above it to get hung. How ever we didn't find a proper solution for this and moved to an alternative method to detect device arrival and removal.
I think windows might not be using the BroadcastSystemMessage() function with the BSF_FORCEIFHUNG flag, while sending the WM_DEVICECHANGE message.