I am using RasDial API inside an MFC application. It turns out that API returns always 633 (The Port Is in Use or Not Configured) while the same code works fine in a command line application.
Here is the code snippet
RASDIALPARAMS rdParams;
ZeroMemory(&rdParams, sizeof(RASDIALPARAMS));
rdParams.dwSize = sizeof(RASDIALPARAMS);
_tcscpy(rdParams.szEntryName, TEXT("VPN"));
m_hRasConn = 0;
DWORD dwRet = RasDial( NULL, NULL, &rdParams, 1, NULL, &m_hRasConn);
The phone book entry for VPN is perfect, it works always when I manually connect and also when I use rasdial.exe
The same entry can be dialed when I use above code inside a command line application but never works when I use it inside MFC application.
Any idea what could go wrong?
From what I can tell, your call to RasDial looks fine.
I remember having this problem during initial development of DotRas. If it's what I'm thinking, if you're testing your application and close the application while a connection attempt is in progress, the RAS state machine gets confused and the connection is left open until you restart (pretty much all versions of Windows pre-Windows 8 exhibit this behavior) the machine.
What this means is, once you start a connection, do not close your application unless you call RasHangUp on the handle that RasDial returned to you if it hasn't finished connecting.
Related
C++, WinRT, VS2017 MFC, Win10
I have a C++/WinRT VS2017 console app as a test platform to find my Bluetooth LE device, enumerate the services and characteristics, and then write a value to the Tx characteristic, etc. I have all of that working and now I am trying to move that code to an existing VS2017 MFC app.
In the console app the BluetoothLEAdvertisementWatcher and callback to the watcher.Received() were done in the main.cpp. Once my BLE device was found, a separate function was called to create the device object from the deviceAddress and then enumerate the services and characteristics.
In the MFC app I created a separate function run in a separate thread to establish the watcher and attach the callback. That all works fine up to the point that it needs to GetGattServicesAsync(). In the console app the function OpenDevice() used to create the device object and get the services was done with a get() as in:
OpenDevice(deviceAddress).get();
The first thing OpenDevice() does is create the device object using
auto device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(deviceAddress);
If the device object is created, then the next thing it did was get the Services with:
auto services = co_await device.GetGattServicesAsync();
Here is where my MFC code fails. In the function thread that creates the watcher and watcher.Received callback my MFC code does the same call to OpenDevice(). In OpenDevice the device object is indeed created but then the call to GetGattServicesAsync() will never finish so matter how long I wait. If I enter the GetGattServicesAsync() in Debug mode, however, then it works fine.
For testing I have also put the OpenDevice() code within the watcher thread but, again, it stalls on GetGattServicesAsync().
In this case, however, I cannot use the co_await but had to use
auto services = device.GetGattServicesAsync().get();
Regardless, the GetGattServicesAsync() never finished.
Any suggestions of what I need to do or what I am doing wrong?
Since running in Debug was working I was trying to solve why this was not working in Release mode. I was relying on my log file entries to track the progress after the fact. For the halibut I put in some Beeps() to let me hear the progress and I was hearing beeps but not seeing log entries after that GetGattServicesAsync(). Apparently what was happening is that, for what ever reason, the GetGattServicesAsync() was NULLing out the handle to my log file so no writes were taking place. I did a check for NULL after the GetGattServicesAsync() and, if it was, re-established the log file. All of a sudden my log file was showing the progress that I thought was not happening. Sometime I think it is just me...:-(
I have a Win32/MFC application that depends on two separate STA COM DLL servers that I created many years ago using C++/ATL. These are large DLL servers with multiple interfaces and are also successfully used in other contexts and client programs. Several years ago, I had to create 64-bit versions of these 32-bit servers, and my 32-bit MFC app needed to be able to use either the 32-bit or 64-bit version of the DLL COM server (chosen with a checkbox).
Because a 32-bit process can't load a 64-bit COM server DLL in-process, I worked around this by having the MFC app create the 64-bit servers in the system surrogate (DLLHOST.EXE) by replacing
CoCreateInstance(..., CLSCTX_INPROC_SERVER, ...)
with
CoCreateInstance(..., CLSCTX_LOCAL_SERVER | CLSCTX_ACTIVATE_64_BIT_SERVER, ...)
Some updates were required, like adding an interface to copy environment variables into the server process and set the server/surrogate's working directory (the surrogate starts in SYSTEM32), but the other interfaces were all remoteable. This all seems to work perfectly and I can now use the 32-bit and 64-bit servers interchangeably from the 32-bit app by flipping a switch.
There is, however, one problem that I haven't been able to solve: making the surrogate quickly terminate when the client releases the last interface. The surrogate hangs around for 3-5 seconds after all remote interfaces are released by the MFC client -- presumably an optimization, hoping the client will come back. If the MFC app re-launches the server with CoCreateInstance() during that 3-5 seconds, it reconnects to the same "dirty" surrogate. The server code is not serially re-usable (it packages up many thousands of lines of legacy ANSI "C" code with lots of static variables) so reconnecting to the same instance is just not possible.
I worked around this several years ago by having the startup interface return a COM error code indicating the server is waiting to be recycled (better than a crash). However, the servers are launched when the end user presses a toolbar button in the MFC app, so this means the user gets a message like "wait a few seconds and try again". That works, but the bad part is that every fresh launch attempt resets the 3-5 second counter that keeps the surrogate from exiting. And impatient users are complaining. I'll add this all works perfectly in-process, with CoFreeUnusedLibraries() working as expected.
I tried a number of things already -- everything short of coding an ExitProcess() in the server, which seems inappropriate. There seems to be no way to tell the surrogate that the application is complete and should not wait for more connections. The MS documentation claims omitting the RunAs attribute in the AppID might help (I had it set to "Interactive User") but it didn't. It also mentions REGCLS_SINGLUSE but then says "Do not set REGCLS_SINGLUSE or REGCLS_MULTIPLEUSE when you register a surrogate for DLL servers" and "REGCLS_SINGLUSE and REGCLS_MULTIPLEUSE should not be used for DLL servers loaded into surrogates." and I don't have control over what the surrogate's class factory as far as I know.
It looks like COM+ might provide some control over recycling, as it seems to have a RecycleActivationLimit option that I might be able to set to 0, but I have no idea what it would take to convert this into a COM+ server.
The other possibility is to write a custom surrogate.
If there's no easy answer, I might just resort to greying out the button until the server vanishes -- but since I can't probe the server without extending its lifetime, I guess I could add a shared mutex and wait for it to vanish. Ugh.
Is RecycleActivationLimit somehow available to regular COM applications? Any other suggestions are most welcome.
Introduction:
I'm an administrator currently working on the dedicated servers of the game "Sniper Elite V2". SEV2's dedicated servers are running under windows in a console application. We are able to run this application under Linux too, with wineHQ. Everything is good, excepted that the console is launched in a new window, so no way to have the console inputs/outputs (link: http://img802.imageshack.us/img802/650/sev22.png). Moreover, we can read (with an HEX editor) that "This program cannot be run in DOS mode". My objective is to bring back DOS compatibility.
My idea is to create another console application written in C++ (with CodeBlocks).
This "Hook" should retrieve the content (text) of the dedicated server "window" and will display it, with the possibility of course to input commands to the dedicated server console. Like that, we will be able to work with inputs/outputs both on Windows and Linux.
I took the time to draw a little schema : http://img195.imageshack.us/img195/3017/29585679.png
My question is: How to do this ? Which functions should I use ?
At this point, I'm stuck. I've tried the following approaches :
FUNC "AttachConsole" has failed.
The following pseudo-code has failed too:
mainWindow = FindWindow( TEXT("ConsoleWindowClass"), NULL) );
console = FindWindowEx( mainWindow, NULL, TEXT("ConsoleWindowClass"), NULL );
SendMessage(
console,
WM_GETTEXT,
sizeof(buffer) / sizeof(TCHAR),
(LPARAM)buffer);
I'm using a tool called "WinSpy++" to help me, but the tool is not able itself to retrieve/input data to the Sniper Elite V2 Dedicated Server.
Any ideas/examples/reflections is welcome :-)
"This program cannot be run in DOS mode"
You make a mistake. Don't mix terms "DOS mode" and "Console". Windows console is NOT a DOS mode. Console is native terminal, where you can run any windows application 32/64 bit, written for console subsystem. "DOS mode" is pre Windows operating system, e.g. DOS, TR-DOS, FreeDOS and so on.
As for question, one console app can not work with two consoles simultaneously.
Upd
Seems that server was builded for GUI subsystem and creates console with AllocConsole.
Run server with 'CreateProcess'
Wait a little while new console wIndow appears.
Call 'FreeConsole' and 'AttachConsole(ServerPID)'
Old
So, if you want to read console_1 from process belonging to console_2, you must
start third process, for example with DETACHED_PROCESS
call FreeConsole (required) and AttachConsole(RootPidFromConsole_1)
communicate between third process and console_2's process (pipes, shared memory, ...)
this works in windows.
I have created a windows service that checks installed printers and updates a file currently located at "C:\App\Data\info" (no file extension) Very simple, all it does is call EnumPrinters with the correct flags and dumps PRINTER_INFO_2 to a file.
Everything works exactly as expected in Visual Studio 2010, in the "testing" project leading me to believe the issue is not in my service. As soon as I install this as a windows service it stops looping. It will run through the loop once and never again.
Code Reference:
I am using the template from here: http://www.kencotutorials.com/WindowsService.aspx
and have only changed the service class file.
Initial thoughts are either security permissions or the wait function not returning.
Edit: I have already checked the whole file system to see if its being written elsewhere and confirmed that it is not.
This is the service loop function that is called by the template.
void CMyService::MyServiceLoop(void)
{
CheckPrinters(); // updates a PRINTER_INFO_2 struct with all installed printers
WritePrinterFile(); // writes the file (i know there's no issue with the actual writing)
Sleep(10000);
OutputDebugString("Done sleeping");
Return;
}
I have added OutputDebugString("Shell loop entered") at the start of the shell app loop.
I have also added OutputDebugString("Waiting for object") in front of the call to WaitForSingleObject()
The loop seems to hang on the WaitForSingleObject. Last message in DbgView is "Waiting for object".
Could be a lot of reasons. I'd recommend you add some OutputDebugString() calls (Win32 API function) and get DbgView.exe from Microsoft to see what is going on. Also, doesn't sound like you are doing this, but make sure you aren't writing to a mapped drive or network location, since your service most likely doesn't have access to those.
When you set up your Windows Service, did you specify an account on the Log On tab?
http://www.coretechnologies.com/WindowsServices/FAQ.html#AppNotWorkingFromService
The default Local System account almost surely doesn't have the rights to use the printers so be sure to set an account that can access the printers normally.
I'm building a custom authentication subpackage for MSV1_0 for Windows 7. I've used the msvsubauth sample in from the Windows SDK and I have 2 questions regarding some problems I'm facing with that:
When I'm trying just to make sure that the routine get's invoked and set the Auth0 property in the registry to my package and add a simple code at the end of the Msv1_0SubAuthenticationRoutine that creates a file:
//
// Cleanup up before returning.
//
Cleanup:
hTestFile = CreateFile(
TEXT("C:\\lsa\\lsa.txt"),
GENERIC_READ|GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if(hTestFile != INVALID_HANDLE_VALUE) {
CloseHandle(hTestFile);
}
return Status;
} // Msv1_0SubAuthenticationRoutine
Apparently the package gets invoked because when I enter my password I get an error message from windows "the parameter is incorrect" which is a good sign. But why I'm getting that error? when the exactly same code is executed from a separate .exe file it runs perfectly and creates the test text file. I've checked the permissions and set "full control" for "everyone". Any ideas? the SDK doesn't exactly mention what kind of isolation LSA is creating for code within auth packages.
The second problem is testing the AP. Currently with every change I rebuild the library, copy it to a test VM and then to the System32 folder and reboot it. Is there an easier way to do that?
Thank in advance!
Debugging in Winlogon and LSASS makes for the most time consuming debugging.
To ease your debugging, you could write a proxy AP that exports the same functions. When loaded, you proxy_ap would
Copy the real AP from a known location to a temp locationand.
LoadLibrary that DLL, GetProcAddress of everything, and forward any calls it receives to that newly loaded DLL.
Watch for changes in the directory where the original AP was copied from
When a change occurs (and if your AP changed) FreeLibrary and goto step 2
But you need to keep a tight grip on what happens on your development target, because handling the dll switch while dealing with requests comming from many threads can become a worse nightmare that what you are trying to solve.
LogonUI.exe starts a new instance every time, but LSASS.exe is long lived.
+Have a look at CVSNT source code (http://cvsnt.sourcearchive.com/). They have a pretty nice AP that implements su. Run the sample in the local system account with psexec -s (from Microsoft/SysInternals pstools suite)
Perhaps your problem is Everyone only includes Authenticated users? This is just a guess.
I suggest you use Process Monitor to monitor for Access Denied messages or for your path. It is fantastic for debugging permission/path problems of all kinds.
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
If you experience the issue at the "Unlock Workstation" or "change Password" screens, and it doesn't prevent you logging in, this should be easy to do - set it running, reproduce the problem, log back in and hey presto.
Otherwise you might have to resort to tricks like executing that code path only for certain user accounts, on the Nth try, etc.