Why RegSaveKey() fails with an error code 5 (access is denied) if the key to be saved is HKEY_LOCAL_MACHINE? - c

This question is independent of the programming language used.
Tested in Windows 7 SP1 and Windows 10 version 1803.
Symptomps
RegSaveKey() fails with an error code 5 (access is denied) if the key to be saved is HKEY_LOCAL_MACHINE.
This error does not occur if a subkey is specified, e.g. HKEY_LOCAL_MACHINE\SYSTEM.
This error also does not occur if the key is HKEY_CURRENT_USER.
First Sample
Here, I use AutoIt to rapidly write a sample code that reproduce the error. I have also compiled the sample code to .EXE to make people easily look at the problem.
Second sample
REG.EXE, which is a built-in Windows tool written using Visual C++ (that's why the tags include C), have exactly the same problem as mentioned above. This is not surprising since according to my investigation, REG.EXE SAVE command actually use the undocumented NtSaveKey(). By the way, RegSaveKey() is internally make a call to NtSaveKey().
REG.EXE SAVE "HKLM" "HKLM.hiv" /Y
The above command fails with an error "Access is denied". Note that I run the command as Administrator.
Question
What is the cause of this error? Is there a way to make RegSaveKey() works for HKEY_LOCAL_MACHINE (without specifying a subkey)?
Update
My further test shows that regedit.exe have the same problem as mentioned above.
Exporting HKEY_LOCAL_MACHINE to a .HIV file fails; however, exporting it to a .REG file succeeds.
Exporting HKEY_LOCAL_MACHINE\<subkey> to a .HIV file succeeds.
Exporting HKEY_CURRENT_USER to a .HIV file succeeds.
Exporting HKEY_CURRENT_USER\<subkey> to a .HIV file succeeds.

All APIs that save a registry key internally call CmSaveKey. In the source code for this function, we see the following block of code at the beginning:
//
// Disallow attempts to "save" the master hive
//
Hive = KeyControlBlock->KeyHive;
if (Hive == &CmpMasterHive->Hive) {
return STATUS_ACCESS_DENIED;
}
HKEY_LOCAL_MACHINE (i.e. "\Registry\Machine") is in the master hive, so CmSaveKey returns STATUS_ACCESS_DENIED (0xc0000022) to the caller. The Windows subsystem translates this status code to ERROR_ACCESS_DENIED (5).

Related

How can i fix on APL2 the generated error code AP211-10

A procedure on APL2 returns the error AP211-10 when it tries to execute a sentence VLIST. When it writes the file, it seems not to have enough space. Where do we have to change the parameter?
In the IBM doc AP211-10 means a problem in I/O file. And it seems related with the common error B37.
The expected result is the creation of the file correctly but actually the file created is corrupted and it is not possible to open on APL2.

wpf localization - locbaml - file is being used by another process

I have been looking hours for a solution, but I donĀ“t find it.
I want to generate a satellite assembly with following command.
locbaml.exe /generate de/App.UI.resources.dll /trans:MeineRess_de.csv /out:de /cul:de
After executing I get following error:
The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0x80070020)
Can anybody help me, Thx
Output to a separate folder try for example c:\ this would work
locbaml.exe /generate de/App.UI.resources.dll /trans:MeineRess_de.csv /out:c:\ /cul:de
For posterity:
The file name without any command line flag is the original input assembly. So you're reading in de/App.UI.resources.dll and then /out:de is trying to write to the same file in the same folder.
Probably you want to change de/App.UI.resources.dll to [UiCulture]/App.UI.resources.dll where [UiCulture] is the <UICulture> from your project file, which should match the NeutralResourcesLanguage attribute in your assembly (AssemblyInfo.cs normally).
Perhaps you legitimately want to overwrite the original DLL (though I don't think that makes sense), but this will not be possible as-is because locbaml will load the assembly from file, which holds the file handle open until the application exits. (Technically until the AppDomain is destroyed.)

How to run an exe using c prog

I am new to this forum. I am in need of a program in C that runs an exe file in Windows.
While googling I found the code below :
1.
Code:
#include<stdlib.h>
#include<stdio.h>
int main()
{
(void)system("C:\\Windows\\notepad.exe");
return 0;
}
The above code compiles successfully in Borland Turbo C. But it fails to run Notepad.
2
Code:
#include<stdlib.h>
#include<stdio.h>
void main()
{
int result ;
result=system("C:\\Windows\\notepad.exe");
printf("%d",result);
}
The above code on running gives -1 as output. Why am I getting -1.
My OS Windows XP
Borland Turbo C Compiler
Please help.
There are at least two wrong things here:
you're using system();
you're hardcoding a path.
For the first problem, I already wrote a long rant some time ago, you can have a look at it here; long story short, to start a process you should go with the platform-specific way, namely, on Windows, CreateProcess or, if you want to open a file with it's associated application, ShellExecute.
For the second problem, you're assuming (1) that c:\windows exists, (2) that it is the windows directory of the currently running windows instance (3) that notepad.exe actually exists and (4) that it is in such directory.
While notepad.exe is pretty much guaranteed to exist on every Windows installation, it's not clear where you should search it. Since Windows 3.0 it was in the Windows directory, but on the NT family it used to stay in the system32 subdirectory. So, from some Windows version onward Microsoft put two copies of notepad, both in the windows directory and in the system32 directory (see this blog post).
Additional fun: from Windows Server 2008 the copy from the Windows directory has been removed (link - incidentally, the title of the post is What idiot would hard-code the path to Notepad? :D), so your program will fail to open notepad even if Windows resides in c:\windows.
But the biggest problem here is that Windows isn't guaranteed to be installed in c:\windows; on every NT-family Windows before Windows XP it was actually installed by default in c:\winnt, so your code would fail here.
Moreover, if you have more than one copy of Windows installed (say Windows 7 64 bit on c:, Windows XP 32 bit on d:) c:\windows may actually exist, but it may contain a copy of Windows different from the one currently executing, so you'd be opening the notepad from another copy of Windows (and if that copy is 64 bit and the running one is 32 bit it won't run).
Similar stuff may happen also if you install Windows on a disk that already contains a windows directory; in that case the setup will put Windows in a Windows(01) directory (or something like that), and c:\windows may be empty.
Long story short:
avoid using system: apart from its other flaws, in all these scenarios your application wouldn't have any clue that notepad didn't start;
avoid hardcoding paths: c:\windows isn't guaranteed to exist; if you need to get the path of the Windows directory, you can expand the environment variable %windir% (or %systemroot), or use the API GetWindowsDirectory;
if your app is in PATH, you may exploit this fact: the Windows and system32 directory are in the PATH environment variable, which means that, if you just try to start notepad, you can avoid to specify it's full path; on the other hand, you're exposing yourself to vulnerabilities if a malicious user put a dangerous application in the working directory of your application;
if you want to open a file, use ShellExecute: it will automatically open that file with the associated application.
I'm not sure notepad has ever been stored in the Windows directory. This code works under WinXP.
#include<stdlib.h>
#include<stdio.h>
/* main() returns int, not void. */
int main( void ) {
int result ;
result=system("C:/Windows/system32/notepad.exe");
printf("%d",result);
return 0;
}
Look where you save your source file, alway C++ Compilers generate two files, let say your source named "hello.cpp"
These files should be in your source path:
hello.obj
hello.exe <--your prgram to distribut
ALSO
I think you should use new free IDE/Compiler for better result such as:CodeBlocks at http://www.codeblocks.org
As per me I dont see any problem with the code, did you try running the program with some standard IDE like, dev-cpp or code-blocks.
And do one thing
try running the same command on the command prompt first and tell the result.
I would also like to tell you to go inside the Windows directory and check if Notepad.exe is there or not.
It is not likely but there is a chance.
Thanks
Alok Kr.
Could be that your path is wrong in some way. I would suggest following Kumar's advice and try running it in the command prompt first just to see that you are using the right path.
Also, you might want to try running notepad.exe without a path at all. As it is located in the PATH, you should be able to specify just "notepad.exe".

fopen fails mysteriously under Windows

Maybe I just have another black out but, this one line is giving me a lot of troubles:
FILE *fp = fopen("data/world.data", "rb");
This works fine under Linux when compiled with GCC. But when I compile it with Visual Studio, it crashes. fp is always NULL. Both the BIN and the EXE are in the exact same directory. Now, to make things even crazier, when I run the EXE using Wine under Linux... it... works...
I have absolutely not a god damn clue what's going on here. Maybe it's some insanely stupid mistake on my side, but I cannot get this thing to run under Windows :/
Also, I have another program which works just fine, there the data files are also contained in a sub directory named data.
EDIT:
To make it clear neither / NOR `\ * do work.
EDIT 2:
OK I've given up on this, maybe someone has fun trying to figure it out, here's ZIP containing the EXE, Debug Data for VS etc.:
https://dl.dropbox.com/u/2332843/Leaf.zip
EDIT 3:
Compiled it with CodeBlocks and MinGW, works like a charm. Guess it has to do something with MSVC or the Project Settings in VS.
It sounds like data isn't a subdirectory of your current directory when you run the program. By default (for x86 targets) VS will build and run your program from either a DEBUG or RELEASE subdirectory of the base directory you've created for the project. You can modify the directory that will be "current" when it runs though (e.g., project | properties | configuration properties | debugging for VS 2008).
Edit: While Windows requires that you use a backslash as a directory separator at the command line, a forward slash works fine in code -- this is not the source of your problem.
In windows you have to write the following:
FILE *fp = fopen("data\\world.data", "rb");
This is like that because the backslash is a special character (so a backslash in a string is written using \ and a quotation symbol is \" and so with other special characters).
Since this issue happens only on windows. I doubt whether the file is really named "world.data". As you know, the default setting for windows hides the file extention. Is its real name world.data.xxx?
Include a line to GetCurrentDirectory(), to see if you are running from the directory you expected.
When I develop in C#/ C++ on visual studio, I normally get to run it from the debug folder. I don't think it matters if forward slash is used in place of backslash in .net.
I happened to have the same problem, and suddenly i figured it out.
That should be your windows fault.
Let's say, FILE *fp = fopen("data/world.data", "rb"); in windows, if you hide the extensions, then you can see the file data/world.data, but actually it maybe /data/world.dat.txt or somewhat.
So please check the extensions.
Hope it helps!
I ran into this today, and it happened because I used "br" instead of "rb" on that mode argument.
The underlying fopen is throwing an exception of some kind, which only registers as a crash. It's not bothering to return the standard NULL response or set the associated error values.
I'm not sure but it may be because you're using slash instead of (an escaped) backslash in the path?

nsinstall: Bad file number error on Vista

I'm attempting to build Firefox on my Windows Vista Ultimate machine. I keep getting the following error:
nsinstall: Bad file number
I've read that this error is caused because of UAC in Vista. Here are the two articles that lead me to this conclusion. https://wiki.mozilla.org/Penelope_Developer_Page#Windows_Vista and http://www.kevinbrosnan.net/mozilla-build-error-nsinstall-bad-file-number
Using the standard "Run as Administrator", I've attempted to redo my build but I get the exact same error. I also started a normal command prompt as admin and then went to the batch file in mozilla-build (start-msvc8.bat) and ran it. Still, same error at the same point.
Any other insights on how I might either get around this error or perhaps something else is causing the error?
Note: I also posted something here in the hopes to get topic-specific help but I've not heard a peep... After I posted that I found the info on nsinstall. Anyway, I prefer SO so I thought I'd try here...
Update: I've attempted to completly disable UAC to correct the problem as is suggested by cnemelkasr. I've received the exact same error. This new knowledge is making me think that a file or folder is missing... Does anyone who has experience with NSInstall know what the given error -- Bad file number -- might mean? I figure it might be referring to a file handle...
If it really is a UAC error, you can try turning off UAC altogether. I've had to do this for several packages. There are numerous places on the web to get the instructions for doing that.
http://www.petri.co.il/disable_uac_in_windows_vista.htm is one of them.
I found the answer to my question. I'm posting the answer here to share the answer with others and to close this question.
After disabling the UAC, it was suggested that the directory depth was interfering with NSInstall. I moved the folder from c:/Users/Frank/Documents/hg-repos/firefox-src-hgRepo/mozilla-fv-expirement/ to C:/mozilla-fv-expirement/. Cleaned all previous build attempts and finally redid my build (with UAC off) and I received a working debug binary.
The suggestion was posted at: mozilla.dev.builds
The "Bad file number" message in the cases I have seen, is caused by too many arguments passed to execvp (command, argv) (or similar) function. But only from some programs. An old bash, sh or a Borland/Watcom program in your PATH is an likely candidate.
So when you shorten the name of the build directory, the total size of the command line (that eventually gets passed to CreateProcess()) gets shorter. I don't think UAC has anything to do with this since I've seen this on Win-XP too. But it's a bit strange Mozilla would not use relative paths while building. I guess it uses some directory prefix value in it's makefiles (I've never tried building it).
If you look at the documentation for _execvp():
http://msdn.microsoft.com/en-us/library/3xw6zy53.aspx
E2BIG is one of the possible errno values:
The space required for the arguments and environment settings exceeds 32 KB.
Now, here is the strange part.
Fact 1:
On Visual-C/MingW (any version), strerror(EBADF) doesn't return "Bad file number" .
(it return "Bad file descriptor").
Fact 2:
On Borland's CBuilder 5.6 and Watcom 1.9 (these do not use the MSVC runtime), strerror(EBADF) does indeed return "Bad file number".
Theory:
Is possible that Borland, Watcom (and other CRTs too?) mixes up the meaning of E2BIG and EBADF. Did that make any sense? Someone please correct me if you have a better theory.
I'm a bit confused myself...
Conclusion: Either shorten the size of your environment (easiest) or shorten the command-line (not always easy).
--gv

Resources