Winamp & Shoutcast Forums

Winamp & Shoutcast Forums (http://forums.winamp.com/index.php)
-   NSIS Discussion (http://forums.winamp.com/forumdisplay.php?f=65)
-   -   Help with ReleaseMutex (http://forums.winamp.com/showthread.php?t=262217)

Clammerz 21st December 2006 15:45

Help with ReleaseMutex
 
Hi, I was wondering if anyone could advise me on how to go about using this API call.

code:
BOOL WINAPI ReleaseMutex(
HANDLE hMutex
);



I have a macro, provided by the wiki pages:
code:
!macro MutexCheck _mutexname _outvar
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${_mutexname}") i .${_outvar} ?e'
pop ${_outvar}
!macroend



Upon reading the "Synchronization Object Security and Access Rights" page on MSDN, I noticed this:
Quote:

MUTEX_MODIFY_STATE (0x0001) Modify state access, which is required for the ReleaseMutex function.
I need to change my macro to include this? So that the installer can modify it?

I'm also not exactly sure how to get the Handle of the Mutex. I'm guessing it's not simply it's name right?

The reason I want to release the Mutex, is that my installer creates two mutex's. One identical to the game I'm trying to patch (so they cannot run the game while trying to patch), and one of it's own, so the user can't run it twice. (reason there being two is that I can set a specific message depending on what the situation is.)

Anyways. At the finish page, I have the option to lauch said game I'm patching. The game won't lauch if it loads faster than the installer can close itself (almost always). So I want to release the Mutex in my Finish Page preFunction.

Thank you very much for your time in reading this.

Red Wine 21st December 2006 16:09

There is a plugin at wiki http://nsis.sourceforge.net/CreateMutex_plug-in that might be helpful.

Clammerz 21st December 2006 19:12

Unfortunately that plug-in only deals with the creation of a mutex. Not releasing one.

Maybe I wasn't direct enough in my first post, I apologise.
What I am after is a basic example of how to use the ReleaseMutex API call using the System plug-in. And also if I need to modify the existing Macro to allow for permissions to release it.

Thank you for your assistance : )

Red Wine 21st December 2006 19:31

You're welcome!
Just found this forum thread.
http://forums.winamp.com/showthread....hreadid=131968
I hope that should be helpful.

Clammerz 22nd December 2006 01:55

Ah, I also came across that thread during my search. While it seemed promising from the title, after the user found out how to create the Mutex, they didn't bother discussing anything further on how to release it. Hee hee~

I guess all the System/API guru's are on holiday at the moment? : (
Oh well, I might have to remove the 'run' tickbox at the end.

Thanks again for your reply.

demiller9 22nd December 2006 04:53

The MSDN page for CreateMutex says the return value is the mutex handle. The macro you have is storing the handle (the return code) in _outvar, but then pops the System::Call return code from GetLastError into the same variable. I suggest changing the macro to put the handle into its own variable:
code:

!macro MutexCheck _mutexname _outvar hMutex
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${_mutexname}") i .${_hMutex} ?e'
pop ${_outvar}
!macroend



And use it something like this:
code:

!insertmacro MutexCheck "myMutex" $0 $1
intCmp $1 0 MutexError
...
System::Call 'kernel32::ReleaseMutexA(i $1) i.r0'
IntCmp $0 0 MutexError2



Don

Mr Inches 22nd December 2006 06:01

Don't forget to use CloseHandle on the mutex when you are done with it - Windows won't destroy it until all processes that have an open handle on the mutex close it.

While it is true that Windows will clean up when the process exits, relying on this is really a sign of poor code; you should always clean up your own resources explicitly.

Duncan

Clammerz 22nd December 2006 09:27

Thank you all very much for your replies!

Here is what I have so far:
Macro:
code:
!macro MutexCheck _mutexname _outvar _hMutex
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${_mutexname}") i .${_hMutex} ?e'
pop ${_outvar}
!macroend



Usage:
code:
!insertmacro MutexCheck "${MyMutexName}" $0 $9
StrCpy $MutexHandle $9
StrCmp $0 0 launch
StrLen $0 "$(^Name)"
IntOp $0 $0 + 1
loop:
FindWindow $1 '#32770' '' 0 $1
IntCmp $1 0 +4
System::Call "user32::GetWindowText(i r1, t .r2, i r0) i."
StrCmp $2 "$(^Name)" 0 loop
System::Call "user32::SetForegroundWindow(i r1) i."
Abort
launch:



Release:
code:
System::Call 'kernel32::ReleaseMutexA(i $MutexHandle) i.r0'
MessageBox MB_OK "Unlocked. Return: $0"



MessageBox is displaying "Return: error"
Hmm, when I use...

code:
System::Call 'kernel32::CloseHandle(i $MutexHandle) i.r0'
MessageBox MB_OK "Unlocked. Return: $0"


It returns 0, but still doesn't lat me lauch.

Does the loop have something to do with it?

kichik 22nd December 2006 11:02

Your MutexCheck macro has syntax errors. i.$$0 is not a valid parameter definition for the System plug-in. You should pass i.r0 instead.

Clammerz 22nd December 2006 18:50

Thanks kichik for your reply.

I was wondering if you could explain a little further about my error.
Sorry to say, but I'm still pretty green on the System plug-in, API calls, and the using the internal NSIS stack itself.

I'm not sure how you are getting i.$$0
Is that from "i .${_hMutex}" ?

I've tried many other arrangements, and I'm still not able to get it working. I even stripped everything down to the very basics:
PHP Code:

System::Call 'kernel32::CreateMutexA(i 0, i 0, t "${MyMutexName}") i.r0 ?e'
Pop $0
StrCpy $MutexHandle 
$0
StrCmp 
$0 0 launch
MessageBox MB_OK 
"Mutant inuse"
   
Abort
  launch
:
MessageBox MB_OK "Mutex open"
System::Call 'kernel32::ReleaseMutexA(i $MutexHandle) i.r0'
MessageBox MB_OK "Mutex released. Return: $0" 

This is very puzzling for me, as I'm really not sure what's going on.
It is returning error. Is that because I'm using invalid parameter definition?
Or is it because I need to change the default security settings of the Mutext itself?

Thank you again for your time.

kichik 23rd December 2006 02:47

It was supposed to be just `i.$0`, I had a typo. System plug-in parameters are divided into three - type, input and output. When you use $0 for the output, the actual value of $0 will be copied into there and you'll eventually get something like `i.123`. This doesn't tell System where to put the value it gets, it tells it what value to put there. You must tell it in which register you want to put the value, and that can only be done with `r*`.

You also have another error there, where the type is wrong. It's a pointer to an integer, not an integer. Use an asterisk before the `i`.

For more information, read the System manual, it has a few step by step guides and some examples.

Clammerz 23rd December 2006 11:58

Thank you kichik.

I finally got it working : )

Here's a snippet if anyone else is having any issues with it:
PHP Code:

!define MyMutexName "MutexNameHere"
!macro MutexCheck _mutexname _outvar _handle
System
::Call 'kernel32::CreateMutexA(i 0, i 0, t "${_mutexname}" ) i.r1 ?e'
StrCpy ${_handle} $1
Pop 
${_outvar}
!
macroend

Function .onInit
!insertmacro MutexCheck "${MyMutexName}$$9
StrCmp 
$0 0 launch
  StrLen 
$"$(^Name)"
  
IntOp $$1
 loop
:
   
FindWindow $'#32770' '' $1
   StrCmp 
$1 0 ++2
   IntOp 
$$1
   IntCmp 
$3 3 +5
   System
::Call "user32::GetWindowText(i r1, t .r2, i r0) i."
   
StrCmp $"$(^Name)" 0 loop
   System
::Call "user32::SetForegroundWindow(i r1) i."
   
System::Call "user32::ShowWindow(i r1,i 9) i."
   
Abort
 launch
:
!
insertmacro MutexCheck "GameMutexHere" $0 $MutexHandle
StrCmp 
$0 0 launchB
StrLen 
$"GameWindowNameHere"
  
IntOp $$1
 loopB
:
   
FindWindow $["ClassHere"] ["GameWindowNameHere"""
   
IntCmp $1 0 +3
   System
::Call "user32::GetWindowText(i r1, t .r2, i r0) i."
   
StrCmp $"GameWindowNameHere" 0 loopB
   MessageBox MB_OK
|MB_ICONEXCLAMATION "Please close Game before continuing."
   
System::Call "user32::SetForegroundWindow(i r1) i."
   
System::Call "user32::ShowWindow(i r1,i 9) i."
   
Abort
 launchB
:
FunctionEnd

Function "PreFinishFunc" ;Finish Page 'pre_function'
System::Call 'kernel32::CloseHandle(i $MutexHandle) i.'
FunctionEnd 

Also, for some strange reason, when using FindWindow, and the '#32770' class, it was returning *every* result before my installer. Even 'console', and '0' ?
So I had to put in a little counter of sorts, to let it find 0 once before skipping ahead to the abort.

As you can see, I'm not the neatest, or most innovative scripter about, so don't expect anything special : P

Thanks once again for everyone's help.

Comm@nder21 23rd December 2006 15:08

sorry, small question:
what do you need "ReleaseMutex" for? :)

i never used it, because every mutex my installers create on startup seem to be released automatically with their shutdown again.

{_trueparuex^} 23rd December 2006 17:16

Quote:

Originally posted by Comm@nder21
sorry, small question:
what do you need "ReleaseMutex" for? :)

i never used it, because every mutex my installers create on startup seem to be released automatically with their shutdown again.

It's in the first post. :p

Comm@nder21 24th December 2006 11:42

ah, read it!
sounds reasonable :)


All times are GMT. The time now is 17:54.

Copyright © 1999 - 2010 Nullsoft. All Rights Reserved.