I'll leave the following here, in case it may help someone else:
"AW" in this thread: http://masm32.com/board/index.php?topic=7755.0 (http://masm32.com/board/index.php?topic=7755.0), provided some really nice code for popping-up the standard Windows 10 screen asking if his program could run as Admin. However, when looking at it (and his asadmin.exe), I found it was a 64-bit solution. Does Windows 10; latest 64-bit version, require such a program to be assembled as 64-bit? Even if it doesn't, WHERE do I get the masm32 equivalent for creating 64-bit executable programs?
If we can do this in a 32-bit program under Windows 10 64-bit, what would be the masm32 version of this code (which looks to me as if it might be something the latest Microsoft assembler could use? Obviously no "masm64rt.inc" here):
INCLUDELIB msvcrt.lib
printf PROTO :PTR, :VARARG
_getch PROTO
INCLUDELIB kernel32.lib
ExitProcess PROTO :DWORD
GetModuleFileNameA PROTO :PTR, :PTR, :DWORD
GetModuleHandleA PROTO :PTR
GetConsoleWindow PROTO
INCLUDELIB Advapi32.lib
OpenSCManagerA PROTO :PTR, :PTR, :DWORD
CloseServiceHandle PROTO :PTR
INCLUDELIB shell32.lib
ShellExecuteA PROTO :PTR, :PTR, :PTR, :PTR, :PTR, :DWORD
INCLUDELIB user32.lib
ShowWindow PROTO :PTR, :DWORD
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
SW_SHOWNORMAL EQU 1
.data
sModuleFileName db 256 dup (0)
runas db "runas",0
asAdminMsg db "Running as Administrator!",10,0
.code
main proc
sub rsp, 38h
mov r8d, GENERIC_READ OR GENERIC_WRITE OR GENERIC_EXECUTE
mov rdx, 0
mov rcx, 0
call OpenSCManagerA
cmp rax, 0
ja @F ; Already Administrator?
call GetConsoleWindow
mov rcx, rax
mov edx, 0 ; Hide the window
call ShowWindow
mov rcx, 0
mov rdx, offset sModuleFileName
mov r8d, 256
call GetModuleFileNameA
mov rcx, 0
mov rdx, offset runas
mov r8, offset sModuleFileName
mov r9, 0
mov rax, 0
mov [rsp+20h], rax
mov eax, SW_SHOWNORMAL
mov dword ptr [rsp+28h], eax
call ShellExecuteA
jmp short @exit
@@: ; Is Administrator
mov rcx, rax
call CloseServiceHandle
mov rcx, offset asAdminMsg
call printf
call _getch
@exit:
mov ecx, 0
call ExitProcess
main endp
end
You must check Integrity level , no "open SCM"
and you have errors in parametres function.
You can use 32bit. It works in Win10x64
.686
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\macros\macros.asm
uselib kernel32,user32,shell32,advapi32
.data
sModuleFileName db 256 dup (0)
runas db "runas",0
asAdminMsg db "Running as Administrator!",10,0
.code
main proc
push GENERIC_READ OR GENERIC_WRITE OR GENERIC_EXECUTE
push 0
push 0
call OpenSCManagerA
cmp eax,0
jnz @f
push 256
push offset sModuleFileName
push 0
call GetModuleFileNameA
push SW_SHOWNORMAL
push 0
push 0
push offset sModuleFileName
push offset runas
push 0
call ShellExecuteA
jmp short @exit
@@: ; Is Administrator
call CloseServiceHandle
push offset asAdminMsg
call OutputDebugStringA
@exit:
push 0
call ExitProcess
main endp
end main
Thank you very much "morgot" for the 32-bit code,
I was able to assemble and link that code just fine, however, I have no idea where to place my code after or wherever in here! The original program left the Console window open with a message (because it had that "_getch" function in it) which is where I was going to add some snippets to see if they function as expected... But your code immediately closes the window, even though I added 10 of these "wait_key" MACROs at various locations in the code!):
inkey MACRO
call wait_key
print chr$(13,10)
ENDM
It always closes the window and I can't see anything... as soon as I press the "Yes" or "No" button to the "Run As Admin" question it closes the windows!
I had intended to print a message to my users, informing them that a copy process was successful and, of course, keep the console window open until they read it and then pressed a key.
TIA,
Dan-TheStarman.
Dan,
Open a DOS prompt and launch it from there, so that you can see the output.
Quote from: jj2007 on January 29, 2021, 07:27:50 PM
Dan,
Open a DOS prompt and launch it from there, so that you can see the output.
That does
not work... the code opens and closes its own console window apart from wherever you run the program; whether in a regular (not Admin) Command Prompt (CMD) or PowerShell (not Admin) Prompt. Did you actually assemble, link and try it?
(And even if it did work there, that would defeat the purpose of it requiring a message be shown to my users later on.)
Hi Dan,
Assuming that your main application has a graphical interface :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc
include \masm32\macros\macros.asm
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\msvcrt.lib
.data
.code
start:
invoke MessageBox,0,\
CTXT("Click OK to display the console window."),\
CTXT("Hello"),0
invoke AllocConsole
invoke StdOut,CTXT("Hello from the console.",13,10)
inkey
invoke ExitProcess,0
END start
Building the application :
\masm32\bin\ml /c /coff TestCons.asm
\masm32\bin\polink /SUBSYSTEM:WINDOWS TestCons.obj
AllocConsole opens a new console window and the output of StdOut is directed to this window.
Quote from: Dan-TheStarman on January 29, 2021, 08:42:55 PMDid you actually assemble, link and try it?
No, it's 64-bit code that works only with a non-standard installation that I don't have, sorry.
If you really want to see the messages, launch a debugger.
Dan,
You cannot mix 32 and 64 bit MASM code, win32 and win64 are different animals. Write the code as 32 bit OR 64 bit but do not try to mix them.
Dan-TheStarman,
you can use kip irvine library , that have simple procedures for Masm (simplier that in C).
Or standart Masm32 (see help dir in masm32 directory)
hello sir Dan-TheStarman;
I forgot command line parameters to console window remain in screen, maybe /c or /k. Can you try? The last windows that I really play seriouos was XP, don't know if this continue working.
Copy and paste link below because last ")" is being ignored
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490880(v=technet.10)
Batch files have PAUSE command, so console window can stay at screen, maybe a try.
I remember now that you can redirect output of a program to a text file. Like:
@echo off
myprogram > myfile.txt
notepad myfile.txt
PAUSE
Quote from: jj2007 on January 29, 2021, 10:23:37 PM
Quote from: Dan-TheStarman on January 29, 2021, 08:42:55 PMDid you actually assemble, link and try it?
No, it's 64-bit code that works only with a non-standard installation that I don't have, sorry.
jj, you really need to start reading the replies! "morgot" provided all the 32-bit code which assembled and linked just fine using masm32 from hutch... my last question to him was how to keep the window open... which it certainly appears you replied to, so then I wrote that no matter what I'd tried, it would always close! Go assemble and link "morgot"'s code... it is 32-bit masm32 code. Dan-TheStarman
Quote from: hutch-- on January 29, 2021, 10:26:31 PM
Dan,
You cannot mix 32 and 64 bit MASM code, win32 and win64 are different animals. Write the code as 32 bit OR 64 bit but do not try to mix them.
hutch, "morgot" already provided the 32-bit code
above in his first reply to me which works just fine in your IDE, etc. Dan.
:biggrin:
Don't worry Dan, we are just trying to keep you safe, sound and coding at the speed of light. :winking:
Quote from: Dan-TheStarman on January 30, 2021, 12:02:45 PM
Quote from: jj2007 on January 29, 2021, 10:23:37 PM
Quote from: Dan-TheStarman on January 29, 2021, 08:42:55 PMDid you actually assemble, link and try it?
No, it's 64-bit code that works only with a non-standard installation that I don't have, sorry.
jj, you really need to start reading the replies! "morgot" provided all the 32-bit code
Sorry, I thought you were referring to your own code.
Quote from: Vortex on January 29, 2021, 10:17:39 PM
Hi Dan,
. . .
include \masm32\macros\macros.asm
. . .
inkey
invoke ExitProcess,0
Hello Vortex,
Thank you for your example.... works fine here. I may eventually place everything that needs to be said to users in graphical windows; forget the console,
however my PROBLEM above is very specific:
I do not understand why placing "inkey" in the code from "morgot" (such as right after "call OutputDebugStringA" or just before the "call ExitProcess") does absolutely nothing to keep the console window open that is created by that "call"?! His code has the same "include \masm32\macros\macros.asm" line yours does... all I can guess is: That "inkey" needs to be inside the (or any?) function you "call"; not outside of it? I also saw your code uses "invoke" for almost everything, whereas
morgot's code is apparently
more granular? (using a number of individual Assembly instructions apart from the "call"s).
Dan.
Hi Dan,
The console in my example is created by the function AllocConsole. Regarding morgot's code, you need to run his code under a debugger to view the output of OutputDebugString :
QuoteIf the application has no debugger and the system debugger is not active, OutputDebugString does nothing
https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-outputdebugstringa
http://masm32.com/board/index.php?topic=6968.0
The inkey macro's job in my code is to keep the console open so the user can read the output and press a key to resume the execution of the application :
invoke StdOut,CTXT("Hello from the console.",13,10)
inkey
invoke ExitProcess,0
Removing inkey here is inconvenient as the user will see only a flashing window.
Regarding the statement invoke :
invoke is one of the post powerfull directives of Masm and compatible assemblers. The job of this macro is to eliminate the unncessary typing of the "push" sequences. Comparing the two approaches :
invoke MessageBox,0,\
ADDR message,\
ADDR caption,0
push 0
push OFFSET caption
push OFFSET message
push 0
call MessageBox
https://docs.microsoft.com/en-us/cpp/assembler/masm/invoke?view=msvc-160
Typing a lof of pushes can be annoying. Consider this example, CreateWindowEx taking 12 parameters :
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW or WS_VISIBLE,100,\
100,500,400,NULL,NULL,\
hInst,NULL
Why morgot prefered push to invoke ? That's a matter of personel preference and there is nothing wrong. In some coding practices, pushing can be more effective than invoking but for the moment those exceptions are not important.
Here is another version of my example :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc
include \masm32\macros\macros.asm
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\msvcrt.lib
.data
message db "Click OK to display the console window.",0
message2 db "Hello from the console.",13,10
db "Please hit a key to continue.",0
message3 db "Click OK to terminate the application.",0
caption db "Hello",0
.code
start:
invoke MessageBox,0,\
ADDR message,\
ADDR caption,0
invoke AllocConsole
invoke StdOut,ADDR message2
invoke wait_key ; \masm32\m32lib\wait_key.asm
; we could also type call wait_key
push MB_OK ; MB_OK = 0
push OFFSET caption
push OFFSET message3
push 0
call MessageBox
invoke ExitProcess,0
END start
EDIT : Reading Timo's message, the introduction of the invoke statement above is corrected. Macro changed to directive.
For OutputDebugString()
https://docs.microsoft.com/en-us/sysinternals/downloads/debugview
Quote from: Vortex on January 30, 2021, 09:03:21 PMinvoke is one of the post powerfull buit-in macros of Masm and compatible assemblers. The job of this macro is to eliminate the unncessary typing of the "push" sequences
The
invoke macro does also type checking, at least for 32-bit code.
Quote from: jj2007 on January 30, 2021, 11:24:39 PM
The invoke macro does also type checking, at least for 32-bit code.
In ml.exe not a macro, a directive
https://docs.microsoft.com/en-us/cpp/assembler/masm/invoke?view=msvc-160
Dan, see it
https://www.masm32.com/board/index.php?topic=5354.0
* removed non working link
this is very simple and usefull library/
Also read the book
https://codernet.ru/books/assembler/assembly_language_for_x86_processors/
http://asmirvine.com/
this is the best book for Masm
or tell in topic, what you need, I can write simple program..
There was no point in what I'd asked here...
Dan, TheStarman.
Program I had started here was based on a false assumption of how "ShellExecuteA" with "runas" was supposed to be used... It's NOT for use inside the program you want to run with elevated privileges!
Dan.
include \masm32\include\masm32rt.inc ; plain Masm32 for the fans of pure assembler
.code
AppName db "Masm32:", 0
start: MsgBox 0, "Hello World, how are you?", addr AppName, MB_OK
exit
end start
If you don't like macros: invoke MessageBox, 0, addr message, addr title, MB_OK
There is a reason why Microsoft created the invoke macro in the 20th Century :cool:
Quote from: jj2007 on February 03, 2021, 10:45:12 PM
If you don't like macros: invoke MessageBox, 0, addr message, addr title, MB_OK
There is a reason why Microsoft created the invoke macro in the 20th Century :cool:
jj, HSE answered the question! I did not realize "addr" was an actual required part of the command... still learning!
But now there's a much bigger issue I've run into both here and under VS2019:
Is there some kind of code we must use to tell the program to ignore all previous references to any windows??
Dan.
Line is:
invoke MessageBoxA, 0, addr winText, addr winCapt, YESNO
Quote from: HSE on February 04, 2021, 08:42:47 AM
Line is:
invoke MessageBoxA, 0, addr winText, addr winCapt, YESNO
Thank you very much HSE!
Dan.
invoke ExitProcess, 0
I have rewrite the first sample for 32 bits,and ... it work in 32 bits
Quote
.data
sModuleFileName db MAX_PATH dup (0)
runas db "runas",0
asAdminMsg db "Running as Administrator!",10,0
.code
manager proc ;
Local hconsole:DWORD,hservice:DWORD,retour:DWORD
mov retour,0
invoke OpenSCManager,0,0,GENERIC_READ OR GENERIC_WRITE OR GENERIC_EXECUTE ;need to be admin to work
mov hservice,eax
.if eax == 0 ;not admin,do it
;invoke GetConsoleWindow
;mov hconsole, eax
;invoke ShowWindow,hconsole,SW_SHOWNORMAL
invoke GetModuleFileName,NULL,addr sModuleFileName,MAX_PATH
invoke ShellExecute,NULL,TXT("runas"),addr sModuleFileName,NULL,NULL,SW_SHOWNORMAL
.if eax <= 32
invoke RetrouveMessageErreur,addr sModuleFileName
.endif
mov retour,1
.else
; Is Administrator
invoke CloseServiceHandle,hservice
invoke printf,addr asAdminMsg
.endif
mov eax,retour
ret
manager endp
return 0 ,it is admin user,just continue
return 1,quit the program
Quote from: HSE on February 05, 2021, 12:37:47 AM
invoke ExitProcess, 0
Wishing I could just delete this!
Dan.
Quote from: Dan-TheStarman on February 05, 2021, 06:37:25 AM
What about the frustrating issue of: Why does program display Info window when answering "Yes" to the UAC runas Admin?
It's not the program.
Quote from: HSE on February 05, 2021, 07:35:36 AM
Quote from: Dan-TheStarman on February 05, 2021, 06:37:25 AM
What about the frustrating issue of: Why does program display Info window when answering "Yes" to the UAC runas Admin?
It's not the program.
As you said, error was... well
maybe technically... "not in the code"; but my in what I expected it to do.
What about reading the FM? Sometimes it helps...
OK,
After going back to the "ShellExecuteA function" documentation at Microsoft, it appears this function when using "runas" is only for executing a program OUTSIDE of whatever program you use it in!
I got it all wrong apparently by assuming the handful of programs I have downloaded from reputable sources that upon execution used the Microsoft Windows UAC display to ask me if they could execute with Admin privileges was a single executable!
I might just as well tell my users to right-click and choose to run my program "as Admin"!
Dan.
I wanted everyone who spent some time on replying to me to know I appreciate it AND that I definitely learned things from all of you!
THANK YOU.
THIS IS NOT a completed CopyMBR program, but after spending all the time here, it does at least incorporate code that checks to see if it is already running with Admin privileges! This is 32-bit assembly code that can be assembled and linked using masm32 and runs just fine... displaying different messages depending upon whether it does or does not have Admin privileges:
.386
.model flat, stdcall
option casemap: none
include \masm32\include\windows.inc
include \masm32\macros\macros.asm
uselib kernel32, user32, shell32, advapi32
; See: https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask-format
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
GENERIC_EXECUTE EQU 20000000h
INFOI EQU 40h
.data
winCapt db "CopyMBR - Copies MBR Sector of Disk 0 to a File", 0
asAdminMsg db "CopyMBR is running with Administrator privileges.", 0
notAdmin db "CopyMBR requires Administrator privileges in order "
db " to copy the Master Boot Record (MBR) sector of this"
db " PC's first disk!", 0dh, 0ah, 0dh, 0ah
db 'Right-click on "CopyMBR.exe" and choose: ', 0dh, 0ah
db '"Run as administrator" to perform this copy operation.', 0
winOpTxt db "If CopyMBR were complete, it would have made a copy of your "
db " first disk's Master Boot Record (MBR) Sector to a file.", 0
.code
main proc
; Note: Only processes with Administrator privileges are able to open a database handle.
; So, first check for Generic Access Rights from the Service Control Manager (SCM) (see both:
; https://docs.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-openscmanagera and:
; https://docs.microsoft.com/en-us/windows/win32/services/service-security-and-access-rights )
; setting "GENERIC ACCESS" rights according to the 'Access Mask Format' found here:
; https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask-format
push GENERIC_READ OR GENERIC_WRITE OR GENERIC_EXECUTE ; 8h OR 4h OR 2h = Eh, so
; we end up with E0000000 if you check registers.
push 0
push 0
call OpenSCManagerA ; No computer name provided, so connects to the SCM on the local
; computer. No database name provided, so SERVICES_ACTIVE_DATABASE
; is opened by default. If successful, return value is a 'handle'
; to the SCM Database. If not, it is NULL.
cmp eax, 0
jnz @F ; If we are already running as Admin (have Generic Read, Write
; and Execute), then jump forward to the nearest "@@:" label.
; Set up the parameters for calling the "MessageBoxA" Function (see:
; https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-messageboxa
; for more information on all the available parameters you could use):
invoke MessageBoxA, 0, addr notAdmin, addr winCapt, INFOI ; Not running with Admin privileges!
push eax ; EAX contains the Exit Code from MessageBox Function which
; can be passed to the ExitProcess (from Kernel32.lib).
; (Exit Codes are 32-bit; even for 64-bit programs.)
jmp @exit ; Jump and use Exit Code from above.
@@:
; Program is already running with Administrator privileges!
invoke MessageBoxA, 0, addr asAdminMsg, addr winCapt, INFOI
; ============================
; Main Body of the code would be here!
; ============================
invoke MessageBoxA, 0, addr winOpTxt, addr winCapt, INFOI
push 0 ; Set exit code to zero.
@exit:
call ExitProcess ; Call Windows API Function "ExitProcess"; no values returned.
main ENDP
END main ; This "END Directive" is required at end of file when
; assembling & linking at a Command Prompt.
; (Note: "end <proc name>" is actually required here by masm32.)
I already made a 64-bit version similar to this under VS2019 Community, and attempted to do so for 32-bit as well, and kept getting so many errors; even after reading a lot about how to write the code, etc. that I soon realized WHY hutch had created his masm32 blog/website and went ahead with what we now have here today! (Writing what VS2019 requires for 64-bit Assembly code is a dream by comparison to 32-bit over there! So all my 32-bit coding will always be done here.)
Dan, TheStarman.
Try naming any 32-bit exe "Setup123.exe" :cool:
I like that trick :thumbsup:
Quote from: jj2007 on February 06, 2021, 07:57:51 PM
Try naming any 32-bit exe "Setup123.exe" :cool:
Thanks jj2007! Works great... All you need to do is put "Setup" in front of your own filename to save users the hassle of clicking and choosing "runas"!
Example: SetupCopyMBR_32.exe
Only primary mouse clicks required.