News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

single instance

Started by xanatose, September 23, 2011, 05:49:08 PM

Previous topic - Next topic

Magnum

I am trying to modify this so it checks to see if explorer.exe is running.




DlgBox      db 'DLGBOX',0,0
ObjectName  db 'explorer.exe',0
errmsg      db 'The application is already running',0
capt        db 'Error',0


.data?

hMutex      dd ?


.code

start:


    invoke  CreateMutex,NULL,FALSE,ADDR ObjectName
    mov     hMutex,eax

    invoke  GetLastError
    cmp     eax,ERROR_ALREADY_EXISTS
    jne     @f
    invoke  MessageBox,0,ADDR errmsg,ADDR capt,MB_ICONEXCLAMATION
    jmp     finish
@@:
    ;invoke  GetModuleHandle,0
    ;invoke  DialogBoxParam,eax,ADDR DlgBox,0,ADDR DlgProc,0

finish:

    invoke  CloseHandle,hMutex
    invoke  ExitProcess,eax


DlgProc PROC hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

    .IF uMsg==WM_CLOSE

            invoke  EndDialog,hWnd,0

    .ELSE

            xor     eax,eax
            ret

    .ENDIF

    mov     eax,1
    ret

DlgProc ENDP

END start

Have a great day,
                         Andy

qWord

hi,
you must enumerate all processes and compare their names wiht your pattern.
FPU in a trice: SmplMath
It's that simple!

dedndave

there is (almost) always one instance of explorer.exe running   :P

Magnum

I am modifying this.

It terminates the app, but always shows that the app has been terminated even when it was never running.


start:

    invoke LoadIcon,hInstance,200    ; icon ID


    invoke GetModuleHandle, NULL
    mov    hInstance,eax
   
    invoke GetCommandLine
    mov    CommandLine,eax
   
    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT

    ; with ReqNTPrivilege call, we ask for the 'SeShutdownPrivilege'
    ; note string names of possible privilege are in windows.inc

    invoke  ReqNTPrivilege, SADD("SeShutdownPrivilege")
    .if eax == FALSE
      invoke  MessageBox,NULL,addr msg_NotPL,addr BoxName,MB_OK
      invoke  ExitProcess,NULL
    .endif

    invoke ExitProcess,eax
   
KillProcess proc lpszExecutable:LPSTR
    LOCAL bLoop:BOOL
    LOCAL bResult:BOOL
    LOCAL pe32:PROCESSENTRY32
    LOCAL hProcess:HANDLE
    LOCAL hProcesses:HANDLE

    mov bLoop,TRUE
    mov bResult,FALSE

    ; Returns an open handle to the specified snapshot if successful or - 1 otherwise.
    invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0
    mov hProcesses,eax    ;  Did not need 2 copies of your snap shot

    mov pe32.dwSize,SIZEOF PROCESSENTRY32

    invoke Process32First,hProcesses,ADDR pe32
    .IF eax
        .WHILE bLoop
            invoke CompareString, LOCALE_USER_DEFAULT, NORM_IGNORECASE, addr pe32.szExeFile, -1, lpszExecutable, -1
            .IF eax==2 ; check if strings are equal in lexical value

                      ;  With having addr pe32.th32ProcessID you were getting an invalid PID
                invoke OpenProcess, PROCESS_TERMINATE, FALSE, pe32.th32ProcessID ; returns handle 

                 .IF eax!=NULL
                    mov hProcess, eax        ; Need to save the process handle to terminate
                    invoke TerminateProcess, hProcess, 0
                    invoke CloseHandle, hProcess ; fails if eax is zero
                   
                    mov bResult,TRUE;
                   
                .endif
            .endif
           ; why go on to next process ?
           invoke Process32Next, hProcesses, ADDR pe32
            ; Retrieves information about the next process recorded in a system snapshot.

            mov bLoop,eax
        .endw
        invoke CloseHandle,hProcesses
    .endif
    mov eax,bResult
    ret

KillProcess endp

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    LOCAL tc   :DWORD

    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_BTNFACE+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
   
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
   
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
   
   
    invoke RegisterClassEx, addr wc

    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\ ; creates a "hidden" window
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
    mov   hwnd,eax

    invoke ShowWindow, hwnd,SW_MINIMIZE    ;Minimal window
    invoke UpdateWindow, hwnd

    ; -------------------
    ; Close screen
    ; -------------------
      invoke SendMessage,hwnd,WM_SYSCOMMAND,SC_CLOSE,NULL

    ;-----------------------------------
    ; Loop until PostQuitMessage is sent
    ;-----------------------------------
    StartLoop:
      invoke GetMessage,ADDR msg,NULL,0,0
      cmp eax, 0
      je ExitLoop
      invoke TranslateMessage, ADDR msg
      invoke DispatchMessage,  ADDR msg
      jmp StartLoop
    ExitLoop:
   
    mov     eax,msg.wParam
    ret

WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   
    LOCAL bResult:BOOL
    LOCAL bLoop:BOOL

    .IF uMsg==WM_DESTROY
        invoke PostQuitMessage,NULL

    .ELSEIF uMsg==WM_CREATE
        mov eax, -1        ;FALSE
       
        mov bResult,eax

        invoke MessageBox,0,OFFSET sucesstext,OFFSET started,MB_OK
        invoke KillProcess,OFFSET ProcessName
                 
        ret
   
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam       
        ret
    .ENDIF
   
    xor eax,eax
    ret
WndProc endp

ReqNTPrivilege proc lpPrivilegeName:DWORD

; return TRUE (not zero) in eax if privilege is granted
; lpPrivilegeName parameter points to a string with request privilege name

    LOCAL   hProcess:DWORD
    LOCAL   hToken:DWORD
    LOCAL   phToken:DWORD
    LOCAL   RetLen:DWORD
    LOCAL   pRetLen:DWORD
    LOCAL   tkp:TOKEN_PRIVILEGES
    LOCAL   tkp_old:TOKEN_PRIVILEGES
;
    invoke  GetCurrentProcess
    mov     hProcess, eax
    lea     eax, hToken
    mov     phToken, eax
    invoke  OpenProcessToken, hProcess, \
            TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, \
            phToken 
    .if eax != FALSE
      lea     eax, tkp.Privileges[0].Luid
      invoke  LookupPrivilegeValue, NULL, \
              lpPrivilegeName, \
              eax
      lea     eax, RetLen
      mov     pRetLen, eax
      mov     tkp.PrivilegeCount, 1
      mov     tkp.Privileges[0].Attributes, SE_PRIVILEGE_ENABLED
      invoke  AdjustTokenPrivileges, hToken, \
              NULL, \
              addr tkp, \
              sizeof tkp_old, \
              addr tkp_old, \
              pRetLen
    .endif
    ret
   
ReqNTPrivilege endp

end start

Have a great day,
                         Andy

dedndave

i am trying to absorb what you are doing   :P

but, i noticed that WM_CREATE may not always return 0
if EAX (from bResult) is -1, it will cause the window to be destroyed
CreateWindowEx will return invalid handle

Magnum

I want to not run a second instance of a program.
Have a great day,
                         Andy

dedndave

i find myself in a similar situation

i know that AV subjects are outside the scope of the forum - so i will leave that part out of the discussion

i want to run a single instance of a program whenever a browser is opened
in this case, i use IE and FF - but any could be added

so - i open the first instance of IE or FF
this is done by running my program, which does some stuff, then runs the browser
once the browser is closed, it does some other stuff
that example demonstrates a single instance of a browser

whenever i open subsequent instances of a browser (either one), it should not do the "stuff"
it should just run the browser
when all instances of the browsers are closed, my program should do the "other stuff", then close
i want to avoid running multiple instances of my program

i looked into event objects, mutex objects, and semaphore objects
none of those seem to be what i need

the current game-plan is to send the browser process handles to the first instance
it keeps a list of all browser process handles
when they are all terminated, the program does "other stuff", then exits
it isn't pretty   :P
maybe someone has a better method

jj2007

I had a clever idea but there is an "e" too much... see yourself:
include \masm32\include\masm32rt.inc

.code
AppName db "Masm32:", 0

start: mov esi, offset AppName
invoke GlobalFindAtom, esi
.if eax
MsgBox 0, "Oh my god, I will disappear immediately", "Atom found:", MB_OK
.else
invoke GlobalAddAtom, esi
push eax
MsgBox 0, "Try to launch a new one, he he!!", "I am the first one:", MB_OK
pop eax
invoke GlobalAddAtom, eax
.endif
exit
end start

Magnum

I still don't understand what an atom table is. ??

n Microsoft® Windows®, an atom table is a system-defined table that stores strings and corresponding identifiers. An application places a string in an atom table and receives a 16-bit integer, called an atom, that can be used to access the string.
Have a great day,
                         Andy

jj2007

Hi Magnum,

An atom table is a global string array with a unique 16-bit identifier.
Just assemble my snippet and test it. Make sure to take out the e in .if eax

Cheers,
Jochen

qWord

Quote from: Magnum on October 22, 2011, 03:36:58 AM
I want to not run a second instance of a program.
In the attachment a function, which returns all instances of a program (PIDs)
FPU in a trice: SmplMath
It's that simple!