Application Behavior Differs on Difference Machines And OSes - c

I'm writing a windows (MS) application to get the name of the process of the active window.
On a desktop PC running 32-bit Windows XP Professional the application runs as expected. But on a laptop machine with a 64-bit Windows 7 Professional OS the does not work as expected. For certain processes an invalid handle is returned. I get the same results on an ultrabook running Windows 8.1 64-bit.
The relevant code snippet is as follows:
DWORD dwThreadID, dwProcessID;
GUITHREADINFO gti;
HANDLE hProcess;
char szProcessFileName[MAX_PATH] = {0};
gti.cbSize = sizeof(GUITHREADINFO);
GetGUIThreadInfo(0, &gti);
dwThreadID = GetWindowThreadProcessId(gti.hwndActive, &dwProcessID);
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);
// Get the name of the process (no error checking for brevity)
GetModuleFileNameEx(hProcess, NULL, szProcessFileName, MAX_PATH);
When the application runs in the non-Windows XP OSes, as stated above, for certain processes OpenProcess and GetModuleFileNameEx fail. GetModuleFileNameEx typically fails with ERROR_PARTIAL_COPY (error code: 299) or ERROR_INVALID_PARAMETER (error code: 87) whereas OpenProcess fails with ERROR_INVALID_HANDLE (error code: 6)
Not sure what's going on. Any help is greatly appreciated. I wonder if it has to do with user permissions.
The source code is compiled as a 32-bit application on a 64-bit machine running Windows 7 Pro x64.

It's a bit of a long read but try... this for starters.
If you are running on XP or above, the recommended workaround to get at the 64-bit process image path from a 32-bit process, is to use the newer GetProcessImageFileName which gets the path (via ProcessImageFileName (27) process information class of NtQueryInformationProcess). The wow64 layer does not do much this time because it is just a unicode string. However this function has a downside – the path returned is of the form /Device/HarddiskVolumeX instead of DOS style drive letter based paths.
Note how the one error was trying to tell you that only 32-bits of a 64-bit address was copied into your pointer. The article describes it better than I can.

Related

OpenProcess returns ERROR_ACCESS_DENIED for 32bit elevated processes

I am looking for a specific eleveated 32bit process on a machine which I would like to terminate. First, I need to be sure it is the right file that is executed.
For that purpose I follow this example by Microsoft of how to get all processes file names using OpenProcess(), EnumProcessModules(), and GetModuleFileNameEx() kernel functions.
When executing from Visual Studio and from an elevated Powershell (x86 or x64) I get an OpenProcess() return code of 299, but the process handle is ok and I can get the file name.
When I run the same binary in an elevated CMD shell (tested on Win10 x64 and Win7 x86) then OpenProcess() return 5 meaning ERROR_ACCESS_DENIED. -- This is a problem to me because for specific reasons the tool will eventually run from CMD.
I have already tried to tweak the desired flags for OpenProcess(), but both versions give the same result as described above.
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE
PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE
HANDLE hProcess = OpenProcess(dwDesiredAccess, FALSE, processID);
EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded);
GetModuleFileNameEx(....);
Thanks in advance for any hints and pointers!
Eventually, I gave up on this in C and implemented it in C# using the System.Diagnostics.Process methods without a flaw.
Thanks anyway for all your efforts!

SHCreateItemFromParsingName return FILE_NOT_FOUND when filename specified

I try get IShellItem for a file to copy it with IFileOperation COM interface from system directory to another directory. I must use exactly IFileOperation COM interface for this purpose.
When I specify full filename - return value from SHCreateItemFromParsingName() was ERROR_FILE_NOT_FOUND, but file present in the directory. When I delete filename from path below and use only folder path - all seems good, return value is S_OK.
//...
CoInitialize(NULL);
//...
WCHAR szSourceDll[MAX_PATH * 2];
wcscpy_s(szSourceDll, MAX_PATH, L"C:\\Windows\\System32\\sysprep\\cryptbase.dll");
r = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_HANDLER, &IID_IFileOperation, &FileOperation1);
if (r != S_OK) return;
FileOperation1->lpVtbl->SetOperationFlags(FileOperation1, FOF_NOCONFIRMATION | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION);
r = SHCreateItemFromParsingName(szSourceDll, NULL, &IID_IShellItem, &isrc);
//...
CoUninitialize();
//...
Why this code, written in C, not working with filenames. How can I create IShellItem instance for file in system folder to copy it?
P.S.
Windows 7 x64, C, Visual Studio 2015, v140 platform toolset, additional dependencies: Msi.lib;Wuguid.lib;ole32.lib;ntdll.lib
P.P.S
It's properly work with files in user`s directories...
Assuming your application is compiled as a 32-bit application and running on a 64-bit OS, a file not found error is probably correct because your application is redirected to the 32-bit system directory (%WinDir%\SysWoW64).
In most cases, whenever a 32-bit application attempts to access %windir%\System32, %windir%\lastgood\system32, or %windir%\regedit.exe, the access is redirected to an architecture-specific path.
For more information, see File System Redirector on MSDN.
You could temporarily turn off redirection in your thread but it is not really safe to do this when calling shell functions, only functions in kernel32. If the API you are calling internally uses LoadLibrary and/or COM then the API might fail because it will be unable to load from system32 while redirection is disabled.
You can also access the native system32 directory with the %WinDir%\SysNative backdoor. This only works in 32-bit applications on 64-bit Vista+ so you must do some version detection.

AppHangXProcB1 on our 32 bit application

We have a C program (a client that connects to our server). The program uses Win32 API:s to create controls etc. It is a single-threaded application. Lately the application has started to hang at random in Windows 7.
Thanks to Application Verifier, I could detect problematic APIs and rectified them.
Now there are still some customers reporting a "non-responsive" situation.
A crash dump from their side reveals the following API:
SendMessage(HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)hClient, MAKELONG(aAppl,aTopic));
Yes its sending a DDE command to WinWord.exe. Task Manager shows Winword in non-responsive state.
Evtx reveals the following:
Fault bucket , type 0
Event Name: AppHangXProcB1
Response: Not available
Cab Id: 0
Problem signature:
P1: OurApplication.exe
P2: 14.14.1.50
P3: 537337f4
P4: b6f1
P5: 32
P6: WINWORD.EXE
P7: 15.0.4615.1000
P8:
P9:
P10:
Attached files:
C:\Users\diane-do\AppData\Local\Temp\WER91C7.tmp.appcompat.txt
C:\Users\diane-do\AppData\Local\Temp\WER958F.tmp.WERInternalMetadata.xml
C:\Users\diane-do\AppData\Local\Temp\WER968B.tmp.xml
C:\Users\diane-do\AppData\Local\Temp\WER969C.tmp.hdmp
C:\Users\diane-do\AppData\Local\Temp\WER9777.tmp.mdmp
These files may be available here:
C:\Users\diane-do\AppData\Local\Microsoft\Windows\WER\ReportQueue\AppHang_OurApplication.exe_e9b582fc22d416b8787c1184f6fe7fa19d63_cab_0fde97a1
Analysis symbol:
Rechecking for solution: 0
Report Id: 9e84daa9-eff8-11e3-a2fb-90b11c841d1a
Report Status: 36
Any help would be appreciated.
Please note the above is Win 7 64-bit, while our application is 32 bit. Don't know what build their Office 2013 is (32 or 64 bit)
I am aware of the following:
- DDE is old technology, but changing it is out of question now.
- For the above case, I cant use SendMessageTimeout APIs as our client has to wait until commands complete.
ONCE AGAIN, The hang (non-responsive state) happens at random, not always at DDE but various instances. While computing something, even while doing a simple operation as below. Customers launch our CHM file from our menu, then Alt+Tab to another application and then Alt+Tab back to our application, our application becomes non-responsive.
P.S: I also didn't find any document online as to how to interpret those evtx application logs , what P1 P2 stand for. What signatures meant or what fault bucket type are, or any meaning of AppHangXProcB1 or AppHangB1 etc. Please pass the link if you have for the same.
sendmessage is a blocking call it will return only after the receiver application processes the message. Here, it got blocked & it as well blocked your application from dispatching the message. Since your application can't process any further window messages, it hanged the GUI.
Check again all the processing done on processing a window message for any blocking calls like waitforsingleobject, recv, connect in it.

How to determine called kernel32.dll function from fault offset

I have an app running as a Windows Service. Today, I was notified that the service died. I found a event viewer entry whose basic info is: faulting module kernel32.dll, version 6.0.6002.18740, time stamp 0x50b58c3d, exception code 0xc0000005, fault offset 0x0003fc2e
I'm sure that there is a bug in my code. Can I determine the kernel32.dll function (where the exception came from) from the offset? I'm planning to backtrack to the call in my code.
I agree with what is said in the comments, but anyway I think the answer can be useful. Here is how you can find function name using Windows debugging tools from SDK provided that EventViewer reported offset of failing instruction in kernel32.dll.
First, install Windows debugging tools and configure path to Microsoft public symbol server. Instructions are available online, for example, this video: http://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-Building-your-USB-thumbdrive
Start windows debugger attached to your process or just any process in the system. kernel32.dll is one of the first DLLs any process loads, it is very unlikely that it is rebased. So kernel32.dll’s base address is the same in all processes.
Get base address of kernel32.dll by running “list modules” command in debugger
0:006> lm m kernel32
start end module name
7c800000 7c8f6000 kernel32 (pdb symbols) c:\debuggers\symbols\kernel32.pdb\A22E3A9843CC45B4A2BFA31377127D422\kernel32.pdb
So the base address is 7c800000. Now run “disassemble single instruction” command using DLL base address and offset:
0:006> u 0x7c800000+0x0003fc2e l 1
kernel32!BasepCopyFileExW+0x859:
7c83fc2e 53 push ebx
So BasepCopyFileExW is the function name. (The result on your system may be different.)

How to get os name, version in windows?

Which one is better in following aspects to get OS name, OS version in windows -
time in getting information
compatibility in all windows OS like xp, vista and higher
systeminfo or wmic command? I wanted to avoid the use of OSVersionInfoEx in C as one has to hardcode the marketing name detection and will add to maintenance work if new flavour of windows gets introduced. Please share your opinion.
GetVersionEx - You can't get any faster than this for getting a basic os version number. But you are right, you won't be able to map newer versions of the OS to the correct string. Have you considered just doing this:
OSVERSIONINFOEX version = {};
char szOS[MAX_OS_LENGTH];
version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx((OSVERSIONINFO*)&version);
if (MyFunctionToMapVersionToString(&version, szOS) == false)
{
sprintf(szOS, "Microsoft Windows %d.%d", version.dwMajorVersion, version.dwMinorVersion);
}
WMI - A bit more code to write. But you could likely just do this at app startup (or when it's needed) and cache the result if the information is needed again. It's not like the operating system product name will change after the app has queried for it once. :) As to backwards compatibility, I'm sure it work fine on older operating systems... but you are going to test it before shipping it to the customer, right?
If you want an undocumented way, there is a registry key that has exactly what you want in it:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion ("ProductName")

Resources