Introduction
There is an IsValidInterface
function in ole32.dll, but it is not being used now. A shape of a function is alive and may be used internally. In Windows, many programmers are using IsBadReadPtr
to validate a pointer and it's useful. Just like this, if you are programming with COM, there is a need for a validation method like COM's version of IsBadReadPtr
. However, MSDN says "This function (IsValidInterface
) is obsolete." I really want to use this function, though, so I try to explore and ask the question, "What is the truth?"
IsValidInterface
IsValidInterface
is declared in ole32.dll. So, we can get the address by the GetProcAddress
API. However, why does MSDN say, "Do not use it!?" In order to answer the question, I disassembled the IsValidInterface
function and translated the C code.
BOOL IsValidInterface(LPVOID lpInterface)
{
if(lpInterface == NULL) {
return FALSE;
}
if(ValidateInPointers( lpInterface ) == FALSE) {
return FALSE;
}
return TRUE;
}
This code is C code of IsValidInterface
(absolutely not full code). Almost, the ValidateInPointers
function returns TRUE
. ValidateInPointers
checks the PEB
element and returns. The element of PEB
which ValidateInPointers
checks is almost 0
. In conclusion, the main code of this IsValidInterface
function is a NULL
check and nothing more. After the analysis, I was disappointed with this function. I don't know about the old code of this function, but now it is only a NULL
checker function and this is not a proper method to validate.
Welcome to the Code of React OS
The React OS is the OS which is similar to Windows. So, almost its source codes are shared with Windows architecture. When I have trouble with programming, I reference the source code of the React OS and it helps me to recognize and figure out problems. The most effective and right way to fix the problems is to analyze Real OS and its code. In the real world, there is no time to do it. The React OS has following code:
BOOL WINAPI IsValidInterface ( LPUNKNOWN punk )
{
return !(IsBadReadPtr(punk,4) ||
IsBadReadPtr(punk->lpVtbl,4) ||
IsBadReadPtr(punk->lpVtbl->QueryInterface,9) ||
IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)
);
}
In this code, confirm the code and interface by IsBadCodePtr
and IsBadReadPtr
and then check the essential points of the COM interface. Pay attention to the 9-byte check with QueryInterface
. The IUnknown
interface's first function is QueryInterface
. So, the 9 bytes from QueryInterface
is also the same COM component and has to exist. Even if there is no real problem, it is not good coding style. It is better code to check 4 bytes than 9 bytes. In addition, Run
operations together with the ||
operator are not good. This is because it is not clear to the sequence of operation. Even though there is a C and C++ standard, this is not good style.
New IsValidInterface
Now, let's make a new IsValidInterface
.
BOOL IsValidInterface ( LPUNKNOWN punk )
{
if(IsBadReadPtr(punk, 4)) {
return FALSE;
}
if(IsBadReadPtr(punk->lpVtbl, 4)) {
return FALSE;
}
if(IsBadReadPtr(punk->lpVtbl->QueryInterface, 3 * sizeof(LPVOID))) {
return FALSE;
}
if(IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)) {
return FALSE;
}
return TRUE;
}
This code is the result of fixing problems which we discussed. I changed 9 bytes to 4 bytes and code sequence.
History
2008-02-01: First released.
2008-02-11: IsValidInterface fucntion update (Size parameter of IsBadReadPtr is changed '3 * sizeof(LPVOID)' from '4'