InternetDial with INTERNET_AUTODIAL_FORCE_UNATTENDED still shows an error dialog? - c++

I have a piece of software running on a remote device which calls InternetDial to establish a connection and report information.
Most of the time this works fine, but occasionally, some sort of error will occurr (bad signal etc.) and despite calling the function with INTERNET_AUTODIAL_FORCE_UNATTENDED, windows still appears to pop up dialogs when it fails to connect.
Rather annoyingly though, these dialogs are modal so the code just locks up.
I've tried just about every combination of options on the network configuration and ways to call the InternetDial routine, but none of them stop that dialog from appearing:
m_DResult = InternetDial(NULL, m_staticModemProfile, INTERNET_AUTODIAL_FORCE_UNATTENDED, (LPDWORD) &m_cnx, NULL);
m_DResult = InternetDial(NULL, NULL, INTERNET_AUTODIAL_FORCE_UNATTENDED, (LPDWORD) &m_cnx, NULL);
m_DResult = InternetDial(NULL, NULL, INTERNET_DIAL_UNATTENDED, (LPDWORD) &m_cnx, NULL);
m_DResult = InternetDial(NULL, m_staticModemProfile, INTERNET_DIAL_UNATTENDED, (LPDWORD) &m_cnx, NULL);
Is there a way round this or another way I can connect? I'm developing on Vista and XP Embedded if that makes a difference.

I just encountered this problem today and this code below fixed my problem. Use InternetAutodial rather than InternetDial
BOOL result = InternetAutodial(INTERNET_AUTODIAL_FORCE_UNATTENDED, NULL);

Related

Issues trying to display a configuration window for my screensaver (from a GUI app running with high mandatory integrity level)

I have an old project that comes with its own screensaver. The GUI application for the project has an option to "Configure screensaver" that should bring up my screensaver configuration window (that you would normally get from a Control Panel -> Display -> Personalization -> Screensaver -> Settings.)
To display the configuration window, one needs to call the screensaver process with the /c parameter as described here. The screensaver itself is placed into the system directory, i.e. "C:\Windows\System32".
So to emulate this from my (32-bit) GUI application I do the following:
//Error checks are omitted for brevity
BOOL bResult = FALSE;
TCHAR buffSysFldr[MAX_PATH];
buffSysFldr[0] = 0;
::GetSystemDirectory(buffSysFldr, SIZEOF(buffSysFldr));
//Make the path, which basically becomes:
// "C:\Windows\System32\mysvr.scr" /c
TCHAR buff[MAX_PATH];
buff[0] = 0;
::StringCbPrintf(buff, sizeof(buff), L"\"%s\\mysvr.scr\" /c", buffSysFldr);
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
ZeroMemory(&si,sizeof(si));
ZeroMemory(&pi,sizeof(pi));
si.cb = sizeof(si);
PVOID OldValue;
Wow64DisableWow64FsRedirection(&OldValue);
//And run it
if(CreateProcess(NULL, buff, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
NULL, NULL, &si, &pi))
{
//Success
bResult = TRUE;
}
Wow64RevertWow64FsRedirection(OldValue);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
When I deploy it to the Windows 7 machine, the code above returns bResult = TRUE but my screensaver's configuration window is never shown.
I tried it on both 32-bit and 64-bit Windows 7 thinking that Wow64 redirection has something to do with it, but it still didn't change the outcome.
Any idea why this doesn't work?
PS. When I copy and paste that command into a command prompt it runs just fine and displays my configuration window w/o a problem:
EDIT: After further review, it turns out that the issue seems to be connected to the fact that my GUI applications runs with High Mandatory Integrity Level, or S-1-16-12288, which seems to be the reason why the screensaver's configuration window is not shown. If I run my GUI app with its regular Medium integrity level, or S-1-16-8192, the configuration window shows OK.
Otherwise, I can see that my screensaver's RegisterDialogClasses method is called OK, but then when I return TRUE from it, ScreenSaverConfigureDialog is never called.
Since integrity level was introduced to prevent processes with lower levels to send messages to processes with higher levels, evidently the screensaver configuration mechanism tries to send some messages to my GUI app (for whatever undocumented reason) and fails and then silently fails as well ...
So this is the latest. I'll appreciate any input on this from whoever knows how to solve this (apart from lowering the integrity level of my GUI app, that I obviously don't want to do.)
God damn Microsoft documentation (sorry, I just wasted the whole day today trying to fix it.)
For whoever else runs into this -- it turns out one needs to call it as such:
"C:\Windows\System32\mysvr.scr" /c:N
where N is a window handle of the parent window expressed as an integer. Found it out by checking command line of the configuration window displayed via Control Panel (did it using Process Explorer.)
In my case, since my GUI process runs with higher integrity level, doing the following will suffice:
HWND hWndToUse = ::GetDesktopWindow();
::StringCbPrintf(buff, sizeof(buff), L"\"%s\\mysvr.scr\" /c:%d", buffSysFldr, (int)hWndToUse);
And that's it!

Auto-generating HTML file & trying to open it in IE sometimes shows a blank page

I have a somewhat strange behavior associated with Internet Explorer (IE). My goal is to generate a report as HTML markup and display it to a user via the web browser. (Since my software is used in our corporate environment and most of those have IE web browsers by default, I observed this issue only with IE.)
The software is written as an MFC dialog-based app, that is run daily (at 7:30 am) from a repeating task scheduler task. (The task is set up to run only when a user is logged on, which is all the time. It's a single user account system, and that user is never logged out. Those machines are also powered on all the time.)
Upon startup my software generates the HTML markup, saves it in a temp file and then has IE display it to the user. That's it. (The goal is basically to automate this report and display it on the screen when the person begins their day.)
So I used basically the following code:
TCHAR buffTempFldr[MAX_PATH] = {0};
::GetTempPath(MAX_PATH, buffTempFldr);
StringCchCat(buffTempFldr, MAX_PATH, L"Log Report.htm");
//strHtml = CStringA with HTML markup of report in 8-bit ASCII format
HANDLE hFile = ::CreateFile(buffTempFldr, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, 0, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
DWORD dwcbWrtn;
::WriteFile(hFile, (BYTE *)strHtml.GetString(), strHtml.GetLength(), &dwcbWrtn, NULL);
::CloseHandle(hFile);
BOOL bInitted = SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
//Show in Web Browser (IE by default)
int nRetSH = (int)ShellExecute(NULL, L"open", buffTempFldr, NULL, NULL, SW_SHOWNORMAL);
if(nRetSH > 32)
{
//Success
}
if(!bInitted)
CoUninitialize();
}
The issue is that this works most of the time, but then maybe 10% of the time a user gets just an empty (blank) HTML page. And only after they hit refresh the page shows the actual report.
Obviously this is confusing for the users, so I'm trying to see why this is happening?
PS. The computers that this is done on are running Windows 7 Professional, and IE v.11, with regularly installed updates.
I might have gotten to the bottom of it.
This looks like a bug in the IE 11 rendering engine. (Interestingly enough, I ran it on a machine with IE 8 and it worked fine.) I discovered this by accident. When IE shows a blank page, if I just slightly resize its window, my HTML markup is then drawn in an instant. This also seems to happen only when I run my page thru IE with the screen being off in the power saving mode (although maybe running screensaver does it too -- I haven't gone all the way to test it.)
So at the moment I chose to use the following "hack" that wakes the screen before I call my ShellExecute method:
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)-1);
::Sleep(500);
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
ShellExecute(NULL, NULL, strSaveFileTo, NULL, NULL, SW_SHOWNORMAL);
But I would strongly recommend against using it, since it creates a race condition, or in other words, there's no way of knowing what happens first, the screen being woken up or IE page being displayed.
As a working solution though one may consider using a different web browser, such as Google Chrome or Firefox that won't have this issue.

INVALID_HANDLE_VALUE when calling CreateFileA several times

I'm using CreateFileA and the first time I call it, it works as expected. But when i call it the second time, it returns handle INVALID_HANDLE_VALUE. What could be the problem? Just for information, I'm calling it every time I need to check if my USB device is connected..
int port = 500;
char port_name [MAX_CAR] = {0};
sprintf_s (port_name, MAX_CAR, "\\\\.\\COM%d", port);
com->id = CreateFileA (port_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
EDIT: I did try to use CloseHandle like CloseHandle(com->id); but it doesn't help.
From the documentation:
When an application is finished using the object handle returned by
CreateFile, use the CloseHandle function to close the handle. This not
only frees up system resources, but can have wider influence on things
like sharing the file or device and committing data to disk. Specifics
are noted within this topic as appropriate.
Use GetLastError to get the error code, and use the FormatMessage to get a human readable error description, or just simply Google the error code.
There are many reasons can cause the same error (CreateFile returns INVALID_HANDLE_VALUE), without the GetLastError, you will very hard to find out what is the real reason.

ShellExecuteW not working well on Windows 8.1?

I call standard ShellExecuteW call on Windows8.1 to open PPS (powerpoint slide) file.
This works just fine on Windows 7. On Windows 8.1. it reports "There is no program associated to open the file". Of course, the file association is set and if file is saved and run from Explorer (double clicked) it opens just fine. I also tried to change association and to associate another program and then associate back to PPS viewer, no improvement. It just doesn't work for W8.1 but the same call works on earlier Windows.
Can anyone give me a clue what might be wrong here?
The code used to open file is very simple and I see no errors with it:
HINSTANCE hinst = ShellExecuteW(NULL, L"open", L"C:\\path\\to\\file.pps", NULL, NULL, SW_SHOWNORMAL);
// Check if result is error
if ((int)hinst <= 32)
{
wchar_t buf[512] = { 0 };
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 512, NULL);
MSGBOX(buf);
}
I use free PPS viewer as found here:
http://www.microsoft.com/en-us/download/details.aspx?id=13
I found something similar which points to that this could be a bug in Win8.1. Can anyone confirm this? Or reveal a workaround?
I found the solution myself.
The problem on W8.1 was that the verb open was not registered to the application so it used different default verb. So if the ShellExecute call is replaced with:
HINSTANCE hinst = ShellExecuteW(NULL, NULL, L"C:\\path\\to\\file.pps", NULL, NULL, SW_SHOWNORMAL);
Then the system looks for a default verb which may or may not be open (usually is), so by not using this verb explicitly it leaves this decision to the system.

Genearting screenshot (BMP) with Windows Service and CreateProcessWithLogonW

I'm trying to create a screenshot application using windows service, that can capture complete screen at regular time intervals. To get started with, I took basic window service example (http://code.msdn.microsoft.com/windowsdesktop/CppWindowsService-cacf4948) and included screenshot utility class in the project and called the capture function in the onStart method of sample windows service. However, I got blank screen shots. Later I realized that windows service runs in different session and hence the screenshots are blank.
S, I decoupled the screenshot utility class and made it as a seperate project and generated a .exe out of it (which is capable of writing logs to a file where ever needed). This time, I used createProcessWithLogonW function to call the executable, so that it will run the exe in specified user domain than the default service session. The following is the code snippet I have been using.
void CSampleService::StartProcess()
{
DWORD dwSize; HANDLE hToken=NULL;
LPVOID lpvEnv; PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
WCHAR szUserProfile[256] = L"";
si.cb = sizeof(STARTUPINFO);
if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
{
logger::Wlog(logger::fileName,"CreateEnvironmentBlock Error");
}
dwSize = sizeof(szUserProfile)/sizeof(WCHAR);
GetUserProfileDirectory(hToken, szUserProfile, &dwSize);
CreateProcessWithLogonW(L"admin", L"MyDomain",L"mypassword",
LOGON_WITH_PROFILE, NULL, L"C:\\Temp\\application.exe",
CREATE_UNICODE_ENVIRONMENT, lpvEnv, NULL, &si, &pi);
DestroyEnvironmentBlock(lpvEnv);
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
I have no errors from the logs i got. when the services get initiated, it gives a warning of interactive service trying to show a message. When I click that, I received a black screenshot again. I know that there are many things involved here, I just gave a high level view of what I'm doing. Also, i'm pretty new to windows programming. Any kind of help is appreciated.
yes, i got that working. we have to acquire the active session-ID (perhaps from opened desktop) and run the process as interactive service in that session context. This should probably solve the capturing screenshots issue. If someone is looking for GUI and service interactions perhaps IPC will be the most convenient way.