WinLockDLL.dll functions in Windows7 - winapi

I'm running an app for testing students, which prevents them from doing anything but the test.
Naturally, the app blocks them from closing it, and blocks them from running the task manager (among other things):
[DllImport("WinLockDLL.dll")]
private static extern int CtrlAltDel_Enable_Disable(bool bEnableDisable);
private void Restrict(bool enabled)
{
CtrlAltDel_Enable_Disable(enabled);
}
The dll contains other functions I use, such as hiding the taskbar and the desktop.
Until recently, the students all had WindowsXP, and it worked.
Recently the students have all upgraded to Windows7, and it stopped working.
During debugging, I've found that Windows7 simply doesn't HAVE WinLockDLL.dll, so I copied the dll to one of the W7 computers and gave the app a try.
This time it found the dll and raised no errors, but the function simply had no effect.
So, does anyone know of an alternative in Windows7?
The closest thing I found was this, in which someone posted that:
All the functions you used in the example crash on Windows 7 unless you change the call to DLL_CALL_STDCALL
"Calling STDCALL" doesn't help, since that is exactly what DllImport does by default.
I've read of alternatives for blocking ctrl-alt-delete, such as canceling the ctrl key or blocking the taskmanager via registry or GPO, but I much prefer a simply alternative for WinLockDLL.dll, which contains several functions I use.
Thanks in advance!

For anyone that finds this in the future. I am creating a library to replace WinLock.dll for Windows 7. The source can be found here.
Win7Lock Github

Related

Can I build a Go program while statically linking some DLLs with it?

If you ran a go app with Windows DLL dependencies on a slow hdd disk, it sometimes occurs that Windows takes too long to load those dll.
If you put your go app into a windows service you get serious problems.
Especially on slow hdd disks, this leads to windows service timeouts and the service will not start.
Is it somehow possible to link those DLLs statically to the go app?
Once the DLLs are loaded everything is fine, but it takes two attempts to get the service running.
But after the first failure, Windows won't try to start the service again, so I have to manually start the service by myself.
Anyone got some ideas?
The short answer is "no": "DLL" stands for "Dynamically-Linked Library", and it's impossible to link a DLL statically.
Basically you have two ways to go, I would say:
Debug the issue.
The default timeout for a Windows service startup
is 30000 ms; that is a lot, so I'm inclined to think
your issue it not loading of DLLs or at least not with
locating and linking them in.
The usual approach is two-pronged:
Isolate possible cases. First, turn your service into
a simple (say, console) program, and see how it starts up
with the cold cache. If the behaviour persists, it will be simpler
to debug than the service.
Study whether some of your DLLs does silly things
like performing network requests in their entry-point function
(colloquially known as "DllMain").
If you're loading the DLLs using LoadLibrary[Ex],
their entry point is called upon those calls.
With that in mind, try adding some tracing to your
DLL initialization code.
If all that fails, try procmon of Sysinternals fame
or similar tools.
Get / produce static builds of those libraries—you will then
be able to link them in statically.
But note that if the issue is in fact has something to deal
with the initialization of those libs, linking them in statically
won't buy you anything—they will be slow already linked, that is.
I'd also note that if my shot in the dark was correct,
and one or more of yout libs tries to access some networked
resource, a simple way to solve the problem might be implementing
proper dependencies for your service—so that it starts up only
when the services it depends on functioning are up (such as
networking, DNS etc).
Consider using LazyDll to speed up your code.

How to find out why a MFC program closes silently

I have the following bug in a program:
An MDI MFC program closes silently on Windows 7 (terminates the process without prompting to save changes and without displaying any "crash" dialog) when the user performs this operation : Click a context menu item.
But this happens only on that PC, at least, for the moment. No other PC has encountered that problem. However the bug can always be reproduced following the same steps but only on that PC.
I want to know the reason but probably the customer won't allow me to install many programs to debug, so I need to be able to log when the program terminates, or print the stack in Release version but I'm quite lost.
I had faced a similar bug before and eventually I fixed it logging line by line and changing the problematic part, but I guess there are much better ways to find bug reasons than this.
I have tried on my development PC to create minidumps on Release mode but if there is no exception thrown on that PC, (I haven't confirmed that yet, though...) maybe it's pointless.
Also used an available class on codeproject (Stackwalker) but I don't manage to print all the function calls. Only on simple console programs, but not on MDI or even SDI.
Any ideas on how to find out the reason? Thanks in advance.

Controlling the Namer in WpfApprovals in ApprovalTests

I ran into a problem with using WpfApprovals on different versions of the OS. My personal laptop is running Windows 7 Enterprise and the build server is running Windows 7 professional. Since the WpfApprovals is using the OS name in the approval file name, the tests are failing on the build server.
I tried a number of options to try to avoid including the OS in the approval name, however, it looks like this behavior is hard coded in WpfApprovals.cs...
public static void Verify(Control control)
{
ApprovalResults.UniqueForOs();
ApprovalTests.Approvals.Verify(new ImageWriter(f => WpfUtils.ScreenCapture(control, f)));
}
... short of creating a modified version of the library that comments out the ApprovalResults.UniqueForOs() call, is there a way to disable including OS info in the approval file name?
While I can appreciate that these tests will fail with different major os versions, they shouldn't fail accross different editions. I noticed that the standard string verifier doesn't force the UniqueForOs style naming.
Good point.
This Wpf is a bit tricky because the consistency is always an issue, but forcing it might not be the best idea, especially with no way to override the default behavior. While we figure out the correct solution for the next version, here are a couple of workarounds for 3.0.5
1) Copy file
You can just copy the approved file over to match both OS versions. This sucks a bit but involves no coding.
2) Customized Wpf call
While you stated not doing this it is a pretty easy fix
public static void Verify(Control control)
{
ApprovalTests.Approvals.Verify(new ImageWriter(f => WpfUtils.ScreenCapture(control, f)));
}
Unfortunately this is it. There is not way to intercept the namer.
Thanks for bring this to our attention!

Troubleshooting VB6 App Crash after XP to Win7 Upgrade

I have a VB6 application that I provide support for. This application works on both Windows XP and Windows 7. Some users were migrated from Windows XP to Windows 7 using the User State Migration tool. These users now receive a generic "Application has crashed" Windows error message when they open certain screens (forms) in the application. My assumption is that there is a missing dll/ocx reference, but I'm having trouble tracking it down.
I've tried many/varied troubleshooting techniques:
Full uninstall and reinstall of my application
Manually re-registering all dll's and ocx's that I know are used
Running Process Monitor on a broken computer and a working computer to compare what dll's and ocx's are accessed. The answer might be here but even after filtering out most of the background noise the amount of data is overwhelming. At a minimum I reviewed all of the calls right before it crashes and all of the calls that were not successful. All of the non-successful calls match between working and non-working.
Installed the Windows Debugger Tools and captured a crash dump. Analyzed the crash dump with DebugDiag. DebugDiag says the exception is in msvbvm60.dll. I tried building a PDB file for my exe and loading it in DebugDiag to get more detail about where the exception is occuring but DebugDiag doesn't want to accept the PDB (might be doing something wrong here, but it just seems to ignore it. This same PDB file works fine when I do remote debugging, however.)
I recompiled my VB6 program without any optimizations in PCode. I've read online that sometimes building in PCode, while bad for performance, will tell you the real exception.
Used the above created PDB file to remote debug the VB6 application. The debugger says that the application crashes after the new window has been created, on a line that sets MousePointer = vbHourGlass... To me it seems unlikely that this is the real cause of the error. There are at least 20 other locations in the program where this same line is called and all work fine.
(Forgot about this one)
Used Dependency Walker and profiled the application on both a working and non-working computer. All errors found by dependency walker were the same between the two computers. There were no additional dependencies found on a working computer, and all missing dependencies on the non-working computer were also missing on the working one.
None of these actions changed my error message or showed me what the error is (unless it really is the mouse cursor issue)... There are no entries in the Windows Event Log related to the app crash.
The non-working and working computers all have the same base Windows 7 image, the only difference is whatever is being changed by USMT, which further convinces me that this is some kind of quirky configuration change or a missing dll/ocx or perhaps an unregistered dll/ocx.
Any ideas or thoughts on how I can track down the root cause of the issue would be greatly appreciated.
Update 1 - Response to questions
#MarkHall I have tried running it as admin, though not with UAC off. The application runs fine on a Windows 7 box as a non-admin with full UAC. Windows XP was 32-bit, Windows 7 is 64-bit, but again it works just fine on a like for like box where the user was not migrated from Windows XP.
#Beaner It's possible that it stores settings somewhere that have been corrupted, but the remote debugging leads me to think that it's more likely something else since it seems to die on a step related to the UI, which then makes me think it's probably a missing dll/ocx reference.
#Bob77 The application is installed into Program Files (x86). While many of the libraries do reside in the same folder, they are all registered.
Peter, often I've noticed that the debugger will indicate a line of code that is actually incorrect, depending on WHERE in the actual assembly language the fault occurs. You should look REAL close around your statement that sets the cursor to vbHourGlass. Your exception is PROBABLY happening BEFORE that line of code, but that line is what the debugger thinks is the actual faulted line of code.
Since you said it happens when a window OPENS, I'd look real close at any ocx's you may have referenced on the form, but perhaps NOT actually being used, or called. You might have one there that you don't intend to be there, that could be causing security issues, or something on Win7? Edit the .frm file by hand if you have to, and look at all the GUIDs the form references.
It is possible that one machine is using PER-USER registration, and the other is using PER-SYSTEM registration?? I don't know...
I would take a much closer look at the form that you are trying to open, and be VERY cautious of everything you are doing in the form load events, and so on. This sounds like it could be something as stupid as Windows Aero being enabled on one system, and not another, or some other sort of "Theme" setting that is throwing the VB Form Rendering routine into a hissyfit... Perhaps even something as stupid as a transparent color index in the icon you selected for that from?
If you are still developing this app, (or at least maintaining it), create an entirely NEW form, and re-create all the controls, etc, on the form (resist the temptation to copy/paste them from the old one...), and then see if THAT does the trick. Then, copy all the event code to the new form one event at a time, with at LEAST enough event code to make the form function, even if it's just a "dead form", that loads no data, or whatever the form is supposed to do. Check and debug after each change, and you WILL find it eventually. Of course, make sure you isolate one of the defunct systems to have a platform that you can duplicate the issue on, or then it's just guessing. I find that using something like Acronis w/ Universal Restore is a great option to then take the image file into a good HV, like VirtualBox, and then restore that image as a VM, so you can debug without interfering with your actual users. This sounds like a lot of work, but then again, so is re-writing an application that already exists, right? :)
Failing THAT... /* and */ are your friends!! (Well, we're dealing with VB, so ' would be your best friend! heh... But I'd start commenting out all the code on the form until that sucker opens. Then once it opens, start putting one line back at a time, and re-running it... That's called "VooDoo Debugging", but sometimes, you gotta do what you gotta do...
THANKS A LOT PETER! :) Now you got ME so involved in this, I feel like I'M the one debugging this sucker! Like if it was MY code I was trying to fix! :)
Let me know if any of this helps... I am actually quite interested in what you discover.

How to prevent Windows from caching Com Class info?

Windows 7 is caching some of the COM class information. Older OSs didn't do this. After the OS looks up theHKCU\Software\Classes\CLSID\{GUID}\LocalServer32 value, it caches the value, and doesn't look it up again.
When we update our software, we place the new updates in a different directory, and then update the HKCU\Software\Classes\CLSID\{GUID}\LocalServer32 value to reflect the new path. The next time the software runs, it will use the latest files if running under older Windows OSs. However, on Windows 7, it will continue to use the older file, until the OS is rebooted.
I ran process monitor, and discovered that under Windows 7, it never reads the registry key again, after the first read. On older OSs, it reads that key every time.
My question is: Is there any way to force Windows 7 to re-read the LocalServer32 information from the HKCU hive each time a new out of proc COM object is created?
I have only been able to solve this problem by...
1: Stopping the Process
2: explicitly unregistering using regsvr32 the library ( or exename /unregserver)
3: Registering the new component
4: Starting the process back up.
I would suspect that it is the Un Reg part that is failing for you. If you are just changing the registry key directly then you should call RegSvr32 /u instead.
Also make sure the new directory location is the current directory when you call RegSvr32.
Note that I have always stopped the process and then unregistered, this is probably a significant detail.
As this is a top result in Google for this narrow-ish problem, I thought it would be valuable to add my troubleshooting outcome for this problem.
I found this response on SO: C# : How to change windows registry and take effect immediately
And linked solution from that answer: Registry Watcher C#
Both of which seem viable options for managing changed keys without forcing a reboot. For us (like the OP) this was when installing updates. For us (possibly unlike the OP) this is infrequent and we decided the effort to implement and test a fix as described was outweighed by the simple solution of requiring a reboot: a process Windows users have come to expect with installing software anyway.

Resources