Delphi create dir under system32 - delphi

i tried to create dir under system32 folder
but no exception shows or errors
note i run it as administrator
//1
if not TDirectory.Exists('C:\Windows\System32\oobe\info') then
TDirectory.CreateDirectory('C:\Windows\System32\oobe\info');
//2
if not DirectoryExists('C:\Windows\System32\oobe\info') then
CreateDir('C:\Windows\System32\oobe\info');
//3
try
ForceDirectories('C:\Windows\System32\oobe\info');
except
ShowMessage('cant create it');
end;

You have a 32 bit process on 64 bit Windows. Hence you are subject to the file system redirector. This redirects system32 to SysWOW64 which is the 32 system directory. You'll find your directory there.
You have these options:
Use the sysnative alias to access the 64 bit system directory.
Run the code in a 64 bit process.
Disable file system redirection.
The final option here is fraught with danger and is not to be recommended.
The documentation gives the details: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187.aspx
Of course, it's plausible that writing to the 32 bit system directory is exactly what you want to be doing and you have not yet realised that.
And finally, it would be remiss of me not to point out that the system belongs to the system and should not be modified by applications.

Related

How can I control the EXE name based on the target platform?

I'd like to have two different exe files, depending on whether it's 32-bit or 64-bit build, e.g., FooBar32.exe and FooBar64.exe. Is there a way to set this or is this going to be a postbuild action?
In Project options under the Application tab there is a setting to change the target file extension. You can use this to change the name of executable of your project for different platforms.
NOTE: This only extends the default name that would be created (project name + Target file extension)
EDIT: As you can see this approach has one drawback and that is that it always add a dot in between the Project name and Target file extension.
But to be honest I rather follow the approach where I configure Delphi to output 32 bit executables in Bin32 and 64 bil executables into Bin64 folder instead of even renaming the main executable. Why?
If your application is using any external dynamic link libraries (dll's) you need to make sure to have them for each suported platform (32 bit executables require 32 bit dll's, while 64 bit executables require 64 bit dll's).
So if you store all these dll's in a single folder you will have to make sure that they are properly named (all 32 bit dll's would have 32 prefix and all 64 bit dll's would have 64 prefix). But that also means that in your code you would need to have specific entries for importing functions from these dll's (one for 32 bit dll and one for 64 bit dll). And that can realy complicate everything.
So making seperate bin folders for 32 bit and 64 bit application versions alows you to have dll's for 32 bit and 64 bit applications with the same names and therefore no need to make any changes in your source code to be able to handle with 32 bit and 64 bit dll's
Not exactly what you need, but may be it helps:
{$IFDEF WIN32}
{$EXTENSION 32.exe}
{$ENDIF}
{$IFDEF WIN64}
{$EXTENSION 64.exe}
{$ENDIF}
So, your executables will be Foobar.32.exe and Foobar.64.exe (with two dots).
Is there a way to set this or is this going to be a postbuild action?
To the best of my knowledge, you cannot use project options to vary the output file name for different target architectures. So, you need to modify the output file name post-build.
For debug purposes you should not, and do not need to rename the executable file. The debugger won't like it if you do. So, deployment is the time to rename.
I do this all the time by having two projects under the project group: FooBar32.exe and FooBar64.exe. FooBar32.exe is set with 32-bit options and FooBar64.exe is set with 64-bit options. Each of the projects share the same units. The easiest way is to create FooBar32.exe with all the necessary files, then create FooBar64.exe, highlight the FooBar32.exe files and drag them to FooBar64.exe. Changes to any of the files affect both projects since they refer to the same files. Just do a Build All from the project group to build both at the same time.

Access Denied when copying DLL files for particular client

We have a small utility which updates our software on client computers by simply copying/replacing certain files. The files consist of both EXE's and DLL's. All works fine, except for one client of ours. They have an Active Directory domain (as many of our clients do) but on every single computer, the DLL files fail to copy with error code 5 (access denied). Even when the application is run as administrator - while logged into the computer as administrator. Happens on all of their XP, Vista, and 7 machines. EXE files are copied/replaced fine, but not DLL files. If the DLL does not exist, it copies fine. But if it needs to replace, it fails.
These files are copied using the API call:
function CopyFile(lpExistingFileName, lpNewFileName: PWideChar; bFailIfExists: BOOL): BOOL; stdcall;
The source is a temp folder automatically created by a self-extracting package, and the destination is wherever our software is installed (identified by a registry key of ours). The destination is most commonly a directory in the C: root, but also happens in the Program Files (x86) and anywhere else on their computers. Their IT person insists that they have no special settings configured in their domain to block this. This is our only client with this problem, and happens on all 20+ of their computers. However, when I manually copy the files through Windows, the files copy/replace just fine. I checked the attributes of these files, and they are not hidden or read-only.
What else do I need to do to ensure proper access? Since running as administrator doesn't do the trick?
Trace your update utility with procMon. You should see ACCESS_DENIED errors. Analyse them. Keep an eye on Impersonation. Also ask them if they any Software IPS, "Angry" Antivirus, or if they have configured Software Restirction/AppLocker. The last ones may not be really connected with your issue, but give them a try.
Unlikely to be a problem, but if your Utility is 32 bit and don't have manifest, it may be silently redirected by the OS (Vista and later).
UPDATE:
If the program is too old (i.e. does not comply MS recommendations for software/data locations) MS ACT (Microsoft Application Compatibility Toolkit (ACT)) can be your friend.

Which midas.dll to use? 32bit datasnap/64bit server

Considering the following:
We have a 32 bit Datasnap server installed on a 64 BIT Windows Server
In embarcadero\rad studio\11.00\redist are 2 folders : 32 bit and 64 bit, with in each a midas.dll.
Which file should we put where?
In windows\system32 or windows\syswow64?
On a 64 bit system:
The 64 bit system directory is named System32.
The 32 bit system directory is named SysWOW64.
If you must copy a DLL into the system directory, make sure that you copy 32 bit DLLs to the 32 bit system directory, and 64 bit DLLs to the 64 bit system directory. That's essential if you want your application to be able to locate the DLL.
Since your code is 32 bit, you need to use the 32 bit DLL.
However, you should probably place the DLL in the same folder as your executable since the Windows system directory is private and reserved for use by the system. Applications should not modify the system directory.
Never put anything in the Windows system directories (unless you have a very, very, very good reason to write there).
It's a very bad practice (dating back to Windows 3.x times and poor developers skills, because those dirs are always in the search path) just leading to troubles (i.e. if another application chnages your DLL with its own with little or no checks). Put the DLL in the application folder. It will ensure your application uses the correct version of the DLL. Or if you have to write it elsewhere for a very, very, very good reason use one of the techniques to add a directory to the search path or redirect DLL loading.
Windows system directories must be regarded as operating system private ones. This kind of practices which Windows doesn't forbids enough are those that often makes Windows a slow and unstable system.
If you're application is 32 bit, you need the 32 bit DLL regarless of the operating system.

External exception C0000006

I've wrote some program in Delphi and when I am running it from a disk on key. At some point I'm required to unplug the disk on key while the application is running. If I do this on a computer with at least 1gb of ram everything is okay. When I do this on a machine with 512mb I get an external exception C0000006. If I'm not mistaken, this is because the OS is trying to read the next line of code but cannot find the resource for it (meaning, the application wasn't loaded to the ram) which is absurd because it's a 500kb application.
How can I solve this? or at least handle this exception in a more elegant way? (Since I can't catch it since it's an external exception).
Oh, and my Delphi application is a console application under windows xp.
What you need to do is tell windows to load your whole program into memory, rather than allowing it to demand load pages when it needs to. I have done this successfully for applications running off a CD. I don't have the code with me right now, but I recall that I found hints on how to do it in source for the fantastic open source install program Inno Setup.
Edit: Actually, after doing a little research, you can use a Delphi compiler directive to tell windows to load the full executable. This works if you have Delphi > 2006. This will have the effect that you will never get the external exception.
Put this line in your applications project file:
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
This tells windows that the executable is going to be used from removable media, so load the the executable into memory (or the swap file). Then you don't need to worry about things like copying the file to the machine first, etc.
Edit 2: I currently have access to Delphi 7 and I can confirm, as noted by others, that this also works with Delphi 7 (and likely Delphi 6) with the following code:
const
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
For Delphi < 6, you can go down the path of forcing the executable to be paged in. There is an example of how to do it in C++ here (unless you find a way to modify the PE header flags after link time, which looks to be complicated)
N#
That's EXCEPTION_IN_PAGE_ERROR. It means that the OS loader failed to page in some data required for the application to run, probably due to an I/O error or other error. Since you're removing the disk, that would make sense.
Perhaps the working set (the set of often-used memory pages) for the application was allowed to grow large enough on 1GB machines such that recourse to the disk to reload pages wasn't necessary, but that wasn't the case on 512MB machines?
I would suggest trying to copy the executable to a temporary location and starting it from there, possibly with delayed deletion; or use some other mechanism to guarantee on-disk backing for all memory pages touched by the application in normal use, and prevent this error in cases of memory pressure, where the OS will trim the working set of running processes.
Like #Barry, I would recommend checking the drive type of the volume that your executable is running from; if it is a removeable drive (and missing a "already in temp" command line parameter) copy the executable (and any of its dependencies) to the user's %TEMP% folder and then re-launch it from there with an extra command line parameter to indicate "already in temp".
Create each temporary file using File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose) (or one of the FileStream constructors that takes a FileOptions parameter), but make sure to hang onto the returned File instance until after the second copy is launched (e.g. in a List<File>).
Copy the contents of each file.
Launch the executable from the temp folder.
Call Close() on each of the File instances saved above.
Exit the original executable.
This way the files get closed regardless of which process finishes first, and the source volume can be removed earlier.
The solution
uses Windows;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}
is available for Delphi since version 6.
There's a Delphi working version of RunImageLocally from MSJ which forces the executable/dll to be paged in. This can prevent C0000006 errors when running from network or removable media...
Check it out at https://github.com/jrsoftware/issrc/blob/master/Projects/SetupLdr.dpr
This exception C0000006 also often occurs if your software is run from a network drive. To prevent that problem you can combine the flag
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
with the following flag:
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;
{$SetPEFlags $0C00}

Why can't my program find its DLLs on Vista 64?

I recently got a new laptop. Unfortunately, it came with Vista. It's been one big hassle getting it to work, and the comp has hardware components for which there are no XP drivers, so I can't "upgrade" to an OS that actually works. I've mostly gotten things working, but one particularly odd problem has me stumped.
I installed Delphi and tried to build a project. It compiled, but wouldn't run. "This application failed to start because sdl.dll was not found." Fair enough. So I grabbed SDL.dll and put it in the C:\windows\system32 folder. (Using Vista 64-bit Home Premium. This is a 32-bit dll, though, so I put it in the 32 folder instead of the 64 one.)
Hit Run again. Same problem. But why? That's where it goes, right? And C:\windows\system32 is in the system path. Anyone know why it can't link to the DLL?
(And yes, I know that I can work around the problem by putting the DLL in the same folder as the .exe. I'm currently doing that as a workaround. It's a bad idea in the long term, though, because I have a handful of different projects that all require SDL.)
That is not a Vista problem, but a 64 bit Windows problem: The name System32 is really confusing, but this is actually the folder where the systems (64 bit) DLLs reside.
So on any 64 bit version of Windows...
... all 64 bit system DLLs are located in C:\Windows\System32.
... all 32 bit system DLLs are located in C:\Windows\SysWOW64.
The name comes from Windows on Windows 64 (WOW64) which is the name of the translation layer allowing 32 bit applications to use the native 64 bit system resources.
Raymond Chen recently addressed the basic reason behind why 32-bit system directories are weird on 64-bit Windows. The first paragraph of the entry is really the key to understanding the reason behind segregated 32-bit directories:
On 64-bit Windows, 32-bit programs run
in an emulation layer...If a 32-bit
program tries to look at the system,
it will see a 32-bit system.
I think you'd have to have separate directories to keep these things all separate and working. The seemingly counter-intuitive name of SysWOW64 for the directory where the files reside is makes more sense when you consider that WOW64 means Windows On Windows 64-bit, which is what the emulater that's mentioned above is called.

Resources