Archive: External DLLs and passing Windows Constants?


External DLLs and passing Windows Constants?
Does anybody have an example of how you might pass windows constants to an external DLL? MSDN shows for user32.dll, you can call SystemParametersInfo to make changes to icons, fonts, desktop, etc. Here's the link of all the possibilities:

http://msdn.microsoft.com/library/de...metersinfo.asp

Is there a way to pass the value of that contant?


You need first to get the constant value in hexadecimal or decimal, name it using a define and use it using System plugin to call the dll. There are some examples of windows constants inside Include\WinMessages.nsh of your NSIS dir.

If you don't know the values in hexa or dec, I'll give 'em if you want.


That's where I was going, but have no way to get the hex values. By the way, how DO you get the hex values?

Here're the constants I'm looking for:
SPI_SETDESKWALLPAPER
SPIF_UPDATEINIFILE
SPIF_SENDWININICHANGE
SPIF_SENDCHANGE

Basically, I'm trying to call user32.dll's SystemParametersInfo method to refresh the desktop wallpaper without a reboot. To date, I haven't seend any NSIS scripting that'll actually pull it of. IF I can manage it, I'll post it to the archive. Thanks for the help!


Ok, I've got this code, and while I''m getting an obvious error code back, does anybody know why or where I'm going wrong?

**************
BEGIN CODE
**************

!define SPI_SETDESKWALLPAPER 20
!define WALLPAPER "%SystemRoot%\Web\Wallpaper\test.html"
!define SPIF_UPDATEINIFILE 0x1
!define SPIF_SENDWININICHANGE 0x2
!define SPIF_SENDCHANGE 0x1

System::Call "user32::SystemParametersInfo(i ${SPI_SETDESKWALLPAPER}, i 0, t ${WALLPAPER}, i ${SPIF_SENDCHANGE}|${SPIF_SENDWININICHANGE}) l .r0"
MessageBox MB_OK "Return Value: $0"

**************
ENDDE
**************

The return value I'm getting is: 4294967297. I get a Desktop flicker, but nothing changes, and the value of WALLPAPER isn't set in the registry.


I got it, tested and everything:

!define SPI_SETDESKWALLPAPER        0x0014
!define WALLPAPER ""%SystemRoot%\Web\Wallpaper\test.html"
!define SPIF_UPDATEINIFILE 0x0001
!define SPIF_SENDWININICHANGE 0x0002

System::Alloc ${NSIS_MAX_STRLEN}
Pop $0
StrCpy $0 "${WALLPAPER}"

System::Call "user32::SystemParametersInfo(i ${SPI_SETDESKWALLPAPER}, i 0, t r0, i ${SPIF_SENDWININICHANGE}) i .r1"

System::Free $0


One thing to learn here: Everytime it says "set parameter to point to a null-terminated string" you have to allocate memory for a variable, use the variable and free its allocated memory.

Deguix - thanks for the help there. I'm not getting the error code anymore, but I am getting a "0" returned from the call - basically a false, and the desktop still doesn't refresh for me. I tested it with some of the default images in windows as well, and they also didn't work.

Is there a way to just broadcast to the system that there was a change in order to trigger a refresh?

By the way, I'm trying this on a Win XP Pro system, but the MDSN docs showed that this should work on Win 9x and up.

Thanks for the help so far!


What? I have Windows XP Home and that code was tested and everything, it even gave 1 as a result.

(Oh... try changing this:

""%SystemRoot%\Web\Wallpaper\test.html"

to this:

"%SystemRoot%\Web\Wallpaper\test.html")


Yeah I did that and checked all the code a few times. I'm not exactly what's going on, but I can't get consistent results. Now I did manage to get it to set a bitmap to the background and refresh, but no go on the html based wallpaper...


Oh yeah, a html as wallpaper... MSDN says that this only works for bitmaps, and I tested w/ bitmaps. So that's why... The only thing I found in my Plataform SDK documentation is about the Active Desktop:

To access the Active Desktop, a client application would need to create an instance of the ActiveDesktop object (CLSID_ActiveDesktop) with the CoCreateInstance function and retrieve a pointer to the object's IActiveDesktop interface.
And there says that we can use AddDesktopItemWithUI or AddDesktopItem methods to add an item to it. And the ApplyChanges method that writes to the registry the changes. This seems complicated...

Now there is a question to everyone, how can I use this type of code using System plugin?

Looks like the system plugin would be able to handle all of that. just a few calls:

One to obtain an instance of the ActiveDesktop.
Then multiple calls to AddItem/AddItemUI
Then the call to apply the changes


Ok, so I'm not going insane.... just using the wrong code :) If anybody does have a method for doing this, please enlighten us!


Ok, in checking the MSDN site and some of the NSIS System usage, I think this is possible to set a wallpaper - I'm just stuck on syntax and usage.

Here's what we'd need to send to the IActiveDesktop instance:

SetWallpaper("path\wallpaper_page",0)
ApplyChanges(dWord)

with dWord being one of these (I suspect AD_APPLY_REFRESH
):
AD_APPLY_ALL
AD_APPLY_BUFFERED_REFRESH
AD_APPLY_DYNAMICREFRESH
AD_APPLY_FORCE
AD_APPLY_HTMLGEN
AD_APPLY_REFRESH
AD_APPLY_SAVE

Now, from the NSIS docs and System DLL usage, here's a chunk of code for getting the wallpaper with this code:


# defines
!define CLSCTX_INPROC_SERVER 1
!define CLSID_ActiveDesktop {75048700-EF1F-11D0-9888-006097DEACF9}
!define IID_IActiveDesktop {F490EB00-1240-11D1-9888-006097DEACF9}
# create IActiveDesktop interface
System::Call "ole32::CoCreateInstance( \
g '${CLSID_ActiveDesktop}', i 0, \
i ${CLSCTX_INPROC_SERVER}, \
g '${IID_IActiveDesktop}', *i .r0) i.r1"
StrCmp $1 0 0 end
# call IActiveDesktop->GetWallpaper
System::Call "$0->4(w .r2, i ${NSIS_MAX_STRLEN}, i 0)"
# call IActiveDesktop->Release
System::Call "$0->2()"
# print result
DetailPrint $2
end:

Now... since I SUCK at using the System DLL, is there any chance somebody could help tweak this?

Also, is there a resource for getting the hex value of the MS dWords? I googled the hell out of it and can't find anything.

Thanks!


The following might help! See http://dotnetforums.net/showthread.p...685#post420685 for more. Unfortunately I know nothing about System DLL

Public Const AD_APPLY_ALL As Integer = AD_APPLY_SAVE Or AD_APPLY_HTMLGEN Or AD_APPLY_REFRESH

Public Const AD_APPLY_BUFFERED_REFRESH As Integer = &H10

Public Const AD_APPLY_DYNAMICREFRESH As Integer = &H20

Public Const AD_APPLY_FORCE As Integer = &H8

Public Const AD_APPLY_HTMLGEN As Integer = &H2

Public Const AD_APPLY_REFRESH As Integer = &H4

Public Const AD_APPLY_SAVE As Integer = &H1


Cool, thanks!
So far, I can run this script:

# defines
!define CLSCTX_INPROC_SERVER 1
!define CLSID_ActiveDesktop {75048700-EF1F-11D0-9888-006097DEACF9}
!define IID_IActiveDesktop {F490EB00-1240-11D1-9888-006097DEACF9}
# create IActiveDesktop interface
System::Call "ole32::CoCreateInstance( \
g '${CLSID_ActiveDesktop}', i 0, \
i ${CLSCTX_INPROC_SERVER}, \
g '${IID_IActiveDesktop}', *i .r0) i.r1"
StrCmp $1 0 0 end

# call IActiveDesktop->SetWallpaper
System::Call "$0->4(t ${WP_Path}${WP_Page}, i 0, )"

# call IActiveDesktop->ApplyChanges
System::Call "$0->4(i ${AD_APPLY_REFRESH})"

# call IActiveDesktop->Release
System::Call "$0->2()"
end:

where I've defined
AD_APPLY_REFRESH as 0x4.

This setup blows up and throws an error window. Imust be close - at the very least I'm causing errors :igor:

Anyone, anyone, bueler?