how to move files on reboot in nsis - nsis

i need to move files on reboot from source to destination. tried below 3 methods and all have failed
IfFileExists "$Temp\test.dll" 0 new_installation
StrCpy $ALREADY_INSTALLED 1
new_installation:
SetOverwrite on
!insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_PROTECTED "$Temp\test.dll" "$WINDIR\test.dll" "$WINDIR"
System::Call "kernel32::MoveFileEx(t '$TEMP\test.dll', t '$WINDIR\test.dll', i 5)"
Rename /REBOOTOK '$TEMP\test.dll' `$WINDIR\test.dll`

We confirmed elsewhere that your direct call to MoveFileEx succeeds. This should mean that the rename operation has been recorded in the registry. You can confirm this with the PendMoves tool from SysInternals. That same page also provides a MoveFile tool you can try.
Assuming the operation has been recorded, you should investigate the reasons the file operation might fail during boot:
One or both files are read-only.
The security descriptor (ACL) blocks the move and/or delete operation.
The file you are trying to replace is a protected system file.
File is locked by the system or a driver.
According to this answer, Process Monitor boot logging is active before the rename operation begins so you could use it to see if it provides any clues as to why the operation fails...

Related

what happens when calling ```touch .``` in linux?

this is a very specific question
I'm mainly interested in the open() system calls the happen when running touch ..
So I ran strace touch . and saw that opennat() is called three times.
but I'm not really understanding whats going on; as touch . does not print anything in the console and does not create a new file named "." since "." is a pointer to the current folder and can be seen by running ls -a so nothing is created since that name is already in use.
this is my assumption:
open() is called to check if the specified file name already exits, if a file descriptor is returned this means that the name is already in use and the operation is canceled.
please correct me if I'm wrong.
GNU touch prefers to use a file descriptor when touching files, since it's possible to write touch - > foo and expect the file foo to be touched. As a result, it always tries to open the specified path as a writable file, and if that's possible, it then uses that file descriptor to update the file timestamp.
In this case, it's not possible to open . for writing, so openat returns EISDIR. touch notices that it's a directory, so its call to its internal fdutimensat function gets an invalid file descriptor and falls back to using utimensat instead of futimens.
It isn't the case that the openat call is used to check that the file exists, but instead that using a file descriptor for many operations means that you don't have to deal with path resolution multiple times or handle symlinks, since all of those are resolved when the file descriptor is opened. This is why many long-lived programs choose to open a file descriptor to their current working directory, then change directories, and then use the file descriptor with fchdir to change back. Any pchanges to permissions after the program starts are not a problem.

CreateFile in separate thread returns INVALID_HANDLE_VALUE in MFC app

I have an MFC App which fires up a separate thread for downloading some files via cURL. At the start it downloads a text file with file sizes and last write times. Then it checks the files on disk and queues it for downloading if it has different values.. The problem is; the CreateFile call in the thread arbitrarily returns INVALID_HANDLE_VALUE. I always do CloseHandle() after a successful CreateFile(). The failing files are just random. Sometimes a file in the root dir, another time a file in a nested directory. The problem is not related to localization or directory/file names since sometimes all checks pass but sometimes don't. GetLastError() return 2 or 3 on occasion which are "File not found" / "Path not found" respectively.
When I put the function checking the file write times and size straight into the OnInitDialog() function, everything works. This smells like a multithreading issue but I double-checked everything from memory allocations to file handles.
The same code works in a console application also in a separate thread.
The platform is Win7 64bit.
Linking statically to the runtime and MFC.
in my case GetCurrentDirectory() returned the system32 path after some time so my code failed because of credentials. I fixed the issue by determining file paths manually (getting the exe path at the start and use it from there on...) . Make sure you are not trying to write to/read from a privileged location on disk. Check your paths.

is there a way to change the target of symlink /proc/self/exe?

hi all:
recently i'm working on make checkpoint on linux process and encountered a problem,it looks like that when i munmap memory map of the executable to current process,the symlink /proc/self/exe is dead.what i want is to make this symlink pointing to a other executable(the one for my resumed processs),is that possible?i tried delete it and recreate, permission denied. english is not my native language, i hope i've made my point,thanx
prctl(PR_SET_MM_EXE_FILE, ...)
Supersede the /proc/pid/exe symbolic link with a new one pointing to a new executable file identified by the file descriptor provided in arg3 argument. The file descriptor should be obtained with a regular open(2) call.
No. /proc is completely managed by the kernel and does not allow changes like that.
But you may be able to start a new process (with fork() perhaps) and map your memory snapshot into that.

Detect if an instance is running with kernel32::CreateMutexA

I'm working on an NSIS installer, and trying to check if a certain application is running before uninstalling. So, I use kernel32::CreateMutexA call. Here is the chunk:
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "cmd.exe") i .r1 ?e'
Pop $R0
StrCmp $R0 0 +3
MessageBox MB_USERICON "The application is already running."
Abort
I put it into un.onInit. Trouble is, the process (cmd.exe here) is never detected.
Did I miss something?
Tx.
I found a simple solution; using FindProcDLL plugin.
So:
FindProcDLL::FindProc "cmd.exe"
Pop $R0
StrCmp $R0 0 +3
MessageBox MB_USERICON "The application is already running." IDOK
Abort
P.S. FindProcDLL.dll must be copied into /Plugins.
All you are doing is creating a mutex with the global name "cmd.exe". From the MSDN article for CreateMutex:
If lpName matches the name of an existing event, semaphore, waitable
timer, job, or file-mapping object, the function fails and the
GetLastError function returns ERROR_INVALID_HANDLE. This occurs
because these objects share the same name space.
So unless cmd.exe creates a handle to one of those types of objects with the name "cmd.exe", this call will simply create a new mutex with that name and return you the (non-erronous) handle.
You're probably using the wrong Win32 API function. Your CreateMutex tries to create a named mutex "something.exe". If there isn't one with that name it will succeed, so unless the process you're trying to check is creating a mutex with that name, you won't get the result you're after.
What you want is probably to enumerate all running processes and see if the one you're after is there. You can do this with ToolHelp32 from Win32 API - see sample here. I don't know how easy it will be to convert it to 'pure' NSIS so you might want to write a DLL plugin, or check if there's an existing solution floating around the NSIS community.
For this kind of thing, I've used either the KillProcess or Find-Close-Terminate plugins for NSIS - see here
Documentation is pretty straightforward, hopefully this does what you need - with a fairly minimal overhead.

Reproducing the blocked exe "unblock" option in file properties in windows 2003

When I download my program from my website to my windows 2003 machine, it has a block on it and you have to right click on the exe, then properties, then select the button "Unblock".
I would like to add detection in my installer for when the file is blocked and hence doesn't have enough permissions.
But I can't eaisly reproduce getting my exe in this state where it needs to be unblocked.
How can I get the unblock to appear on my exe so I can test this functionality?
This is done using NTFS File Streams. There is a stream named "Zone.Identifier" added to downloaded files. When IE7 downloads certain types of file that stream contains:
[ZoneTransfer]
ZoneId=3
The simplest way to set it is to create a text file with those contents in it, and use more to add it to the alternate stream.
Zone.Identifier.txt:
[ZoneTransfer]
ZoneId=3
Command:
more Zone.Identifier.txt > file.exe:Zone.Identifier
Then, the way for you to check it would be to try to open the Zone.Identifier stream and look for ZoneId=3, or simply assume that if the stream exists at all that your user will receive that warning.
It's also important to note that this has nothing to do with permissions. Administrators see the same warning; it's to do entirely with the source and type of file. The entire stream goes away when users uncheck the "Always ask before opening this file" box and then click Run.
There is a supported API for this, documented on MSDN. Search on MSDN for "Persistent Zone Identifier Object". Basically you CoCreateInstance with CLSID_PersistentZoneIdentifier and request an IPersistFile interface. You then call IPersistFile::Load with the name of the file in question. Next, QI for an IZoneIdentifier interface and use IZoneIdentifier::GetId to obtain the zone of the file. If there was no "mark of the web", you should get URLZONE_LOCAL_MACHINE. The ZoneId of 3 mentioned in the other reply is URLZONE_INTERNET. (The enumeration is called URLZONE and is also documented on MSDN, or see sdk\inc\urlmon.h.) You can remove or change the "mark of the web" by calling IZoneIdentifier::Remove or IZoneIdentifier::SetId and then call IPersistFile::Save. There are more details about all of this on MSDN. Good luck!
Thanks for this it helped me a lot.
You can make the process even easier if you create a batch file with the contents.
echo [ZoneTransfer] > Zone.Identifier
echo ZoneId=3 >> Zone.Identifier
more Zone.Identifier > %1:Zone.Identifier
This will generate the Zone.Identifier for you and mark the file accordingly.
To run it just supply the file name e.g. if the file is called mark.bat
mark.bat myfile.txt

Resources