Well I think if it's going to be a UDF it should be modified a little bit.

As for free tools out there to do this, take a look at RockXP
http://www.rockxp.org/

Download here:
http://korben.othersystem.net/web/softs/RockXP3.exe

Recommended UDF changes

Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)
$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")
If @ERROR
;ChangeVLKey should not have a value if we got an error
$ChangeVLKey = 0
;Convert the error to readable format
Exit Val('&' + Right(DecToHex(@ERROR), 4))
EndIf
For Each $obj in $objects
$ChangeVLKey = $obj.SetProductKey($VOL_PROD_KEY)
Next
;Assumes we got here okay so exit with no error
Exit 0
EndFunction