What's the purpose of SetRegView lastused? - nsis

What's the purpose of SetRegView lastused?
The docs only talk about the 32/64 bit registry views, which I understand.
I thought it might be acting as a stack, like this person, being able to switch back to the view before the one currently in use. But the response to someone asking that question was:
No stack. Just the last one used.
In which case, if you're already in the 32 bit view, it's just equivalent to SetRegView 32? That doesn't seem right, what am I missing?
My google-fu only got me so far, finding this example from Mozilla (snippet from full script):
; Since the Maintenance service can be installed either x86 or x64,
; always use the 64-bit registry.
${If} ${RunningX64}
; Previous versions always created the uninstall key in the 32-bit registry.
; Clean those old entries out if they still exist.
SetRegView 32
DeleteRegKey HKLM "${MaintUninstallKey}"
; Preserve the lastused value before we switch to 64.
SetRegView lastused
SetRegView 64
${EndIf}
Then in a couple places later in the script:
${If} ${RunningX64}
SetRegView lastused
${EndIf}
Looking at the context there, if you call SetRegView 32, followed by SetRegView lastused, does that mean any future uses of SetRegView lastused will always result in the 32 bit registry view?

Not it is not a stack (but you could argue that it should be). It is simply the last set 32/64 state.
The SetRegView instruction is transformed into a NSIS opcode called EW_SETFLAG by MakeNSIS and its implementation in a installer looks something like this:
if (get_last_used)
g_exec_flags[flag] = g_exec_flags_last_used[flag] ; Restore previous
else
g_exec_flags_last_used[flag] = g_exec_flags[flag] ; Set last used
g_exec_flags[flag] = new_value ; Assign new value
These flags are also available to plug-ins in the exec_flags_t struct.
It is only useful if you mainly deal with one registry view but once in a while need to read from the other view:
Section
SetRegView 64
ReadRegStr $0 HKLM "Software\Foo" "Bar"
SetRegView lastused ; We are now back to the default view (32-bit in this case)
SectionEnd
or if you mainly use the 64-bit view:
Function .onInit
SetRegView 64
FunctionEnd
Section
SetRegView 32
ReadRegStr $0 HKLM "Software\Foo" "Bar"
SetRegView lastused ; We are now back to the previous view (64-bit in this case)
SectionEnd
I guess it is implemented this way because it simply reuses the lastused functionality used by other flags. It also simplifies things because it never has to allocate more memory. I also don't know why it is undocumented.

Related

Does WINE implement "_printf" and similar functions in MSVCRT?

Here is an example program that illustrates my problem, it can be compiled using FlatAssembler without using a linker:
format PE console
entry start
include 'win32a.inc'
section '.text' code executable
start:
mov dword [esp],_output1
call [printf]
mov dword [esp+4],first
mov dword [esp],_input
call [scanf]
mov dword [esp],_output2
call [printf]
mov dword [esp+4],second
mov dword [esp],_input
call [scanf]
finit
fld dword [first]
fabs
fld dword [second]
fxch
fld1
fxch
fyl2x
fldl2e
fdivp st1,st0
fmulp st1,st0
fldl2e
fmulp st1,st0
fld1
fscale
fxch
fld1
fxch
fprem
f2xm1
faddp st1,st0
fmulp st1,st0
fstp dword [result]
fld dword [result]
fst qword [esp+4]
mov dword [esp],_output
call [printf]
invoke system,_pause
invoke exit,0
_output1 db "Enter the first number: ",0
_output2 db "Enter the second number: ",0
_input db "%f",0
_pause db "PAUSE",0
_output db "The first number to the power of the second number is: %f.",10,0
section '.rdata' readable writable
result dd ?
first dd ?
second dd ?
section '.idata' data readable import
library msvcrt,'msvcrt.dll'
import msvcrt,printf,'printf',system,'system',exit,'exit',scanf,'scanf'
So, the expected output is, of course, something like this:
Enter the first number: -2.5
Enter the second number: -2
The first number to the power of the second number is: 0.16
And that's the output I indeed get if I run that program on Windows 10. However, if I try to run that program on WINE on Oracle Linux, the output I get is:
000f:fixme:service:scmdatabase_autostart_services Auto-start service L"MountMgr" failed to start: 2
000f:fixme:service:scmdatabase_autostart_services Auto-start service L"WineBus" failed to start: 2
wine: Bad EXE format for Z:\home\teo.samarzija\Documents\Assembly\debug.exe.
Any idea what's going on?
I've done a little research, and I can't find any reference confirming that _printf and _scanf are even implemented in WINE's MSVCRT. However, I am not sure that's the problem, and, if it is a problem, that that's the only problem.
However, if I try to run that program on WINE on Oracle Linux, the
output I get is:
000f:fixme:service:scmdatabase_autostart_services Auto-start service L"MountMgr" failed to start: 2
000f:fixme:service:scmdatabase_autostart_services Auto-start service L"WineBus" failed to start: 2
wine: Bad EXE format for Z:\home\teo.samarzija\Documents\Assembly\debug.exe.
A "Bad EXE format" error is something different entirely. It doesn't imply that the problem is a missing imported function. The loader never got that far. It wasn't even able to read your binary. This is very likely caused by a bitness mismatch. For example, trying to run a 64-bit application on a 32-bit system.
Aside from this problem, it is worth pointing out that your attempted use of C runtime library functions is inherently non-portable. It might work, if Wine (or whatever other runtime environment) provides a function with an identical signature, but it very likely won't.
I suppose I should further clarify, since calling a standard C runtime library function "non-portable" may raise a few eyebrows. These functions are portable at the source-code level, but not at the binary level. Even without the added complexity of Wine, the C runtime library functions are non-portable, as Microsoft's CRT is versioned—you have to link to the appropriate version and have that DLL available at runtime, or your application will not work.
This exact problem is why Windows provides wrappers for these standard functions as part of the basic platform API, which is universally available. If you want to be fully portable to all implementations of the Win32 environment, and you aren't linking in your own copy of the C runtime library, then you should call these functions instead.
The Win32 version of the sprintf function is wsprintf. It has the same interface as sprintf, so you can call it the same way, as a drop-in replacement. In fact, although you shouldn't rely on this, it is implemented by Windows as a simple wrapper around the sprintf version provided by the local copy of the C runtime libraries.
If you want a version to which you can pass an argument list (a la vsprintf), then you can call wvsprintf.
Note that, unlike most of the Windows API functions, these functions use the __cdecl calling convention, not the __stdcall calling convention. Make sure that you are adhering to that in your assembly code. In short, that means passing arguments from right-to-left and cleaning up the stack at the call site.
Microsoft has, however, deprecated these functions, as they aren't entirely safe (buffer overflows and etc. are possible). As replacements, they offer the functions in the StrSafe.h header. These functions come in two variants: those which take a count of bytes (Cb) and those which take a count of characters (Cch). The relevant ones to this discussion would be either StringCbPrintfA or StringCchPrintfA. These are trickier to use from assembly language, however, because they're meant to be used inline by simply including the StrSafe.h header file. You can use them in library form, but then you'll need to pass the corresponding StrSafe.lib stubs to the linker. Note that linking to this library means your application will only run on Windows XP with SP2 or later.
This gets you halfway there. You are actually trying to call printf, rather than sprintf. The gap, of course, is getting the formatted string written to the console. Once you have the formatted string (generated by wsprintf, StringCchPrintfA, or whatever), that can be accomplished by calling the WriteConsole function, which is the Win32 API for writing output to the console window. If you want STDOUT, then you need to open that handle first with GetStdHandle(STD_OUTPUT_HANDLE).
Anyway, I got the answer:
https://www.linuxquestions.org/questions/linux-general-1/can%27t-install-wine-on-64-bit-oracle-linux-4175655895/page2.html#post6012838
In short, on 64-bit Oracle Linux, WINE needs to be compiled from source to work properly.

Registers like $0

Can someone explain and/or provide reference for understanding how NSIS registers work. For example, $0, $1. I see examples of using them.
Like {If} $0 == ''
Do something
I don't understand how you can put values into $0 or how values are there dynamically?
Please help, thank you.
From the NSIS Sourceforge docs, located here, Registers are already-defined variables available for use:
These variables can be used just like user variables, but are usually used in shared functions or macros. You don't have to declare these variables so you won't get any name conflicts when using them in shared code. When using these variables in shared code it's recommended that you use the stack to save and restore their original values. These variables can also be used for communication with plug-ins because they can be read and written by the plug-in DLLs.
Variables are handled like strings in NSIS, so to put a value into one of these Register variables, such as $0, you would do a command like:
StrCpy $0 WhatValueYouWantToBeInZero

what's the meaning of ENTRY statement in entry.S in Linux kernel for i386

for example in entry.S
ENTRY(ret_from_fork)
pushl %eax
call schedule_tail
GET_THREAD_INFO(%ebp)
popl %eax
jmp syscall_exit
so what's the syntax of ENTRY in as language?
I think all the directive of as is start with . and the ENTRY also doesn't look like a macro
can anyone tell me about the ENTRY is what? if it is defined in Linux source code could anyone indicate the location or if it is a syntax in as can someone tell me where i can find the specific description of this use!
Thanks!
Not sure why you say it doesn't look like a macro, because that's exactly how macros look like. And indeed it is a macro defined in include/linux/linkage.h as follows:
#ifndef ENTRY
#define ENTRY(name) \
.globl name ASM_NL \
ALIGN ASM_NL \
name:
#endif
I think that's an assembler directive .
As per my knowledge ENTRY assembler directive is used when we use Keil assembler.
That's actually the entry point of a application.
The way we have _start or _main entry point in assembly code when we use GNU assembler.

How can I use variable on NSIS include / to get another variable

Is there anyway to include file by mention it with variable? I mean
StrCpy $1 "bla.nsh"
!include $1
?
or maybe getting value of variable that called by another variable such as:
StrCpy $1 "EN"
StrCpy $2 ${LANG_${1}_WELCOME_MESSAGE}
?
Thanks.
Variables can only be used at runtime (running on the end-users machine), you need to use defines:
!define foo "bar"
!include "${foo}.nsh"
Edit:
You should be using the LangString instruction if you want to add custom translated strings, you can access a langstring at runtime with $(mystringid).
Actually, Anders right. Think about that, when the compiler compiling your code, it need to know which files it need to include with your EXE file.
About the variable, you can use only with defines. again, because when you are compiling, the compiler will compile all the needed (in use) variables / defines, and you can't tell him use one that never been declared.. its little different from server side languages because here you are compiling and pack your code into EXE file which is assembled in your computer.

How to put assembly markers to C++ code (x64)

I need to put markers to C++ code that should be visible in assembly or binary. It seems it’s straight forward to do it for 32 using inline assembly:
__asm {
NOP
NOP
NOP
}
or using DB assembly statement:
__asm {
DB 0x00, 0xFF, 0x10
}
But VisualStudio 2005 and better does not support inline assembly for x64. Is there any way to do it? Probably I can make a function in separate assembly module but how I can be sure that linker will put an actual assembly there instead of CALL?
Define a global volatile variable somewhere, say volatile __int64 blah = 0;. Then wherever you want some marker, use _InterlockedCompareExchange64(&blah, SOME_UNIQUE_CONSTANT1, SOME_UNIQUE_CONSTANT2);. You'll be guaranteed to find instructions loading ECX:EBX with SOME_UNIQUE_CONSTANT1 and EDX:EAX with SOME_UNIQUE_CONSTANT2 followed by LOCK CMPXCHG8B (0xF0, 0x0F, 0xC7, etc -- see instruction encoding details).
The MSDN says you can use intrinsic functions.
//MyAsmCode.asm
.code
MyFunction proc
...
MyFunction endp
end
compile it (ml64.exe).
You get object file (MS COFF 64): MyAsmCode.obj
In VS add MyAsmCode.obj to linker additional dep.
Now you can call this function. ;)

Resources