From ba4020488ce4588519ff122e46f8092a1f54bdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 9 Nov 2014 20:11:31 +0100 Subject: [PATCH] installer sets language to application download PlayerGlobal.swf from installer --- installer.nsi | 280 ++- src/com/jpexs/decompiler/flash/gui/Main.java | 43 + .../sun/jna/platform/win32/Advapi32Util.java | 1964 ++++++++--------- src/com/sun/jna/platform/win32/Kernel32.java | 5 + 4 files changed, 1293 insertions(+), 999 deletions(-) diff --git a/installer.nsi b/installer.nsi index eb3575503..a1b266f22 100644 --- a/installer.nsi +++ b/installer.nsi @@ -16,17 +16,19 @@ + +!define APP_SHORTVERNAME "JPEXS FFDec v. ${APP_VER}" + !define APP_VERNAME "${APP_NAME} v. ${APP_VER}" !define MUI_WELCOMEFINISHPAGE_BITMAP "graphics\installer_164x314.bmp" !define MUI_HEADERIMAGE -!define MUI_HEADERIMAGE_BITMAP "graphics\installer_150x57.bmp" +!define MUI_HEADERIMAGE_BITMAP "graphics\installer_150x57.bmp" !define APP_UNINSTKEY "{E618D276-6596-41F4-8A98-447D442A77DB}_is1" - SetCompressor /SOLID lzma ;Name and file - Name "${APP_VERNAME}" + Name "${APP_SHORTVERNAME}" OutFile "${APP_SETUPFILE}" @@ -44,8 +46,15 @@ SetCompressor /SOLID lzma ;Interface Settings !define MUI_ABORTWARNING + !define MUI_LANGDLL_ALLLANGUAGES + +!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.ModifyUnWelcome +!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.LeaveUnWelcome +!insertmacro MUI_UNPAGE_WELCOME +!insertmacro MUI_UNPAGE_INSTFILES + !include LogicLib.nsh @@ -76,6 +85,103 @@ Function GetInstalledSize Push $GetInstalledSize.total FunctionEnd + + +Function IsFlashInstalled + Push $R0 + ClearErrors + ReadRegStr $R0 HKCR "CLSID\{D27CDB6E-AE6D-11cf-96B8-444553540000}\InprocServer32" "" + IfErrors lbl_na + IfFileExists $R0 0 lbl_na + StrCpy $R0 1 + Goto lbl_end + lbl_na: + StrCpy $R0 0 + lbl_end: + Exch $R0 + FunctionEnd + +!define IsFlashInstalled "!insertmacro IsFlashInstalled" + +!macro IsFlashInstalled ResultVar + Call IsFlashInstalled + Pop "${ResultVar}" +!macroend + + +!define StrLoc "!insertmacro StrLoc" + +!macro StrLoc ResultVar String SubString StartPoint + Push "${String}" + Push "${SubString}" + Push "${StartPoint}" + Call StrLoc + Pop "${ResultVar}" +!macroend + +Function StrLoc +/*After this point: + ------------------------------------------ + $R0 = StartPoint (input) + $R1 = SubString (input) + $R2 = String (input) + $R3 = SubStringLen (temp) + $R4 = StrLen (temp) + $R5 = StartCharPos (temp) + $R6 = TempStr (temp)*/ + + ;Get input from user + Exch $R0 + Exch + Exch $R1 + Exch 2 + Exch $R2 + Push $R3 + Push $R4 + Push $R5 + Push $R6 + + ;Get "String" and "SubString" length + StrLen $R3 $R1 + StrLen $R4 $R2 + ;Start "StartCharPos" counter + StrCpy $R5 0 + + ;Loop until "SubString" is found or "String" reaches its end + ${Do} + ;Remove everything before and after the searched part ("TempStr") + StrCpy $R6 $R2 $R3 $R5 + + ;Compare "TempStr" with "SubString" + ${If} $R6 == $R1 + ${If} $R0 == `<` + IntOp $R6 $R3 + $R5 + IntOp $R0 $R4 - $R6 + ${Else} + StrCpy $R0 $R5 + ${EndIf} + ${ExitDo} + ${EndIf} + ;If not "SubString", this could be "String"'s end + ${If} $R5 >= $R4 + StrCpy $R0 `` + ${ExitDo} + ${EndIf} + ;If not, continue the loop + IntOp $R5 $R5 + 1 + ${Loop} + + ;Return output to user + Pop $R6 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch + Pop $R1 + Exch $R0 +FunctionEnd + Function GetTime !define GetTime `!insertmacro GetTimeCall` @@ -216,6 +322,40 @@ Function GetTime Exch $0 FunctionEnd +Function RIndexOf +Exch $R0 +Exch +Exch $R1 +Push $R2 +Push $R3 + + StrCpy $R3 $R0 + StrCpy $R0 0 + IntOp $R0 $R0 + 1 + StrCpy $R2 $R3 1 -$R0 + StrCmp $R2 "" +2 + StrCmp $R2 $R1 +2 -3 + + StrCpy $R0 -1 + +Pop $R3 +Pop $R2 +Pop $R1 + +Exch $R0 +FunctionEnd + +!macro StrRPos Var Str Char +Push "${Char}" +Push "${Str}" +Call RIndexOf +Pop $1 +StrLen $0 ${Str} +IntOp ${Var} $0 - $1 +!macroend + + +!define StrRPos "!insertmacro StrRPos" ;-------------------------------- ;Pages @@ -245,6 +385,18 @@ var SMDir !insertmacro MUI_LANGUAGE "English" !insertmacro MUI_LANGUAGE "Czech" + !insertmacro MUI_LANGUAGE "SimpChinese" + !insertmacro MUI_LANGUAGE "Dutch" + !insertmacro MUI_LANGUAGE "French" + !insertmacro MUI_LANGUAGE "German" + !insertmacro MUI_LANGUAGE "Hungarian" + !insertmacro MUI_LANGUAGE "Polish" + !insertmacro MUI_LANGUAGE "Portuguese" + !insertmacro MUI_LANGUAGE "PortugueseBR" + !insertmacro MUI_LANGUAGE "Russian" + !insertmacro MUI_LANGUAGE "Spanish" + !insertmacro MUI_LANGUAGE "Swedish" + !insertmacro MUI_LANGUAGE "Ukrainian" @@ -252,14 +404,13 @@ var SMDir ;Installer Sections -LangString Sec1Name ${LANG_ENGLISH} "FFDec" -LangString Sec1Name ${LANG_CZECH} "FFDec" -LangString Sec2Desktop ${LANG_ENGLISH} "Desktop Shortcut" -LangString Sec2Desktop ${LANG_CZECH} "Zástupce na Ploše" +LangString Sec3PlayerGlobal ${LANG_ENGLISH} "PlayerGlobal.swc (download)" +LangString Sec3PlayerGlobal ${LANG_CZECH} "PlayerGlobal.swc (stažení)" -Section !$(Sec1Name) SecDummy + +Section "FFDec" SecDummy SetShellVarContext all @@ -284,10 +435,11 @@ Section !$(Sec1Name) SecDummy ;Store installation folder - DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "DisplayName" "${APP_NAME} (remove only)" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "DisplayName" "${APP_NAME}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "UninstallString" '"$INSTDIR\Uninstall.exe"' WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "QuietUninstallString" '"$INSTDIR\Uninstall.exe" /S' + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "DisplayIcon" '"$INSTDIR\ffdec.exe"' WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "DisplayVersion" "${APP_VER}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "URLInfoAbout" "${APP_URL}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "URLUpdateInfo" "${APP_URL}" @@ -295,6 +447,9 @@ Section !$(Sec1Name) SecDummy WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "Publisher" "${APP_PUBLISHER}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "InstallLocation" "$INSTDIR" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "Inno Setup: Icon Group" "$SMDir" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "NSIS: Language" "$language" + + Call GetInstalledSize WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" "EstimatedSize" $GetInstalledSize.total @@ -311,29 +466,112 @@ Section !$(Sec1Name) SecDummy SectionEnd -Section !$(Sec2Desktop) + + + +var txt +var pos +var pgfound +var f +var pgname + +Section "PlayerGlobal.swc" SecPlayerGlobal + +!tempfile PGHTML +inetc::get /SILENT /USERAGENT "${APP_NAME} Setup" https://www.adobe.com/support/flashplayer/downloads.html ${PGHTML} +Pop $0 +StrCmp $0 "OK" dlok +MessageBox MB_OK|MB_ICONEXCLAMATION "PlayerGlobal.SWC was not found on Adobe webpages. Click OK to abort installation" /SD IDOK +Abort +dlok: + +StrCpy $pgfound 0 + +FileOpen $f ${PGHTML} r +loop: + FileRead $f $txt + IfErrors done + StrCmp $pgfound 1 0 nolicheck + ${StrLoc} $pos $txt "
  • " + StrCmp $pos "" nolicheck + IntOp $pos $pos + 13 + StrCpy $txt $txt "" $pos + ${StrLoc} $pos $txt "$\"" ">" + StrCpy $txt $txt $pos + StrCpy $pgfound 2 + Goto done + nolicheck: + ${StrLoc} $pos $txt "PlayerGlobal" ">" + StrCmp $pos "" loop + StrCpy $pgfound 1 + Goto loop +done: + FileClose $f + StrCmp $pgfound 2 +3 + MessageBox MB_OK|MB_ICONEXCLAMATION "PlayerGlobal.SWC not found on Adobe Webpages, click OK to abort installation" /SD IDOK + Abort + + ${StrRPos} $pos $txt "/" + IntOp $pos $pos + 1 + StrCpy $pgname $txt "" $pos + SetShellVarContext current + + CreateDirectory "$APPDATA\JPEXS\FFDec\flashlib" + inetc::get /USERAGENT "${APP_NAME} Setup" $txt "$APPDATA\JPEXS\FFDec\flashlib\$pgname" +SectionEnd + +Section "Desktop Shortcut" SetShellVarContext all CreateShortCut "$DESKTOP\${APP_NAME}.lnk" "$INSTDIR\ffdec.exe" "" SectionEnd Function .onInit - # set section 'test' as selected and read-only + !insertmacro MUI_LANGDLL_DISPLAY IntOp $0 ${SF_SELECTED} | ${SF_RO} - SectionSetFlags ${SecDummy} $0 + SectionSetFlags ${SecDummy} $0 FunctionEnd ;-------------------------------- ;Descriptions ;Language strings - LangString DESC_SecDummy ${LANG_ENGLISH} "Application GUI and Libraries" - LangString DESC_SecDummy ${LANG_CZECH} "Aplikační rozhraní a knihovny" + ;LangString DESC_SecDummy ${LANG_ENGLISH} "Application GUI and Libraries" + ;LangString DESC_SecDummy ${LANG_CZECH} "Aplikační rozhraní a knihovny" + + ;LangString DESC_PlayerGlobal ${LANG_ENGLISH} "Download FlashPlayer library from Adobe site - useful for ActionScript direct editation and other features" + ;LangString DESC_PlayerGlobal ${LANG_CZECH} "Stáhnout knihovnu FlashPlayeru ze stránek Adobe - užitečné pro přímou editaci ActionScriptu a další věci" ;Assign language strings to sections !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN - !insertmacro MUI_DESCRIPTION_TEXT ${SecDummy} $(DESC_SecDummy) + !insertmacro MUI_DESCRIPTION_TEXT ${SecDummy} "Application GUI and Libraries" + !insertmacro MUI_DESCRIPTION_TEXT ${SecPlayerGlobal} "Download FlashPlayer library from Adobe site - useful for ActionScript direct editation and other features" !insertmacro MUI_FUNCTION_DESCRIPTION_END + +;LangString DESC_UninstLocal ${LANG_ENGLISH} "Remove user configuration" +;LangString DESC_UninstLocal ${LANG_CZECH} "Odstranit uživatelskou konfiguraci" + + + + +Var mycheckbox +Var uninstlocal + +Function un.ModifyUnWelcome +${NSD_CreateCheckbox} 120u -18u 50% 12u "Remove user configuration" +Pop $mycheckbox +SetCtlColors $mycheckbox "" ${MUI_BGCOLOR} +;${NSD_Check} $mycheckbox ; Check it by default +FunctionEnd + +Function un.LeaveUnWelcome +StrCpy $uninstlocal 0 +${NSD_GetState} $mycheckbox $0 +${If} $0 <> 0 + StrCpy $uninstlocal 1 +${EndIf} +FunctionEnd + ;-------------------------------- ;Uninstaller Section @@ -353,9 +591,17 @@ Section "Uninstall" !insertmacro MUI_STARTMENU_GETFOLDER 0 $SMDir RmDir /r "$SMPROGRAMS\$SMDir\*.*" - RMDir "$SMPROGRAMS\$SMDir" + RmDir "$SMPROGRAMS\$SMDir" + StrCmp $uninstlocal 1 0 +5 + SetShellVarContext current + RmDir /r "$APPDATA\JPEXS\FFDec\*.*" + RmDir "$APPDATA\JPEXS\FFDec" + RmDir "$APPDATA\JPEXS" + DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APP_UNINSTKEY}" SectionEnd + +;TODO: FlashPlayer detection/install, Java detection/install \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 0d52256cf..7e5cfaa2d 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; import com.jpexs.decompiler.flash.console.ContextMenuTools; +import static com.jpexs.decompiler.flash.console.ContextMenuTools.getAppDir; import com.jpexs.decompiler.flash.gui.debugger.Debugger; import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; @@ -48,6 +49,9 @@ import com.jpexs.helpers.ProgressListener; import com.jpexs.helpers.Stopwatch; import com.jpexs.helpers.streams.SeekableInputStream; import com.sun.jna.Platform; +import com.sun.jna.platform.win32.Advapi32Util; +import com.sun.jna.platform.win32.Kernel32; +import com.sun.jna.platform.win32.WinReg; import java.awt.AWTException; import java.awt.Frame; import java.awt.GraphicsEnvironment; @@ -816,6 +820,45 @@ public class Main { if (GraphicsEnvironment.isHeadless()) { //No GUI in OS return; } + if (!Configuration.locale.hasValue()){ + if (Platform.isWindows()) { + //Load from Installer + String uninstKey = "{E618D276-6596-41F4-8A98-447D442A77DB}_is1"; + uninstKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uninstKey; + try { + if (Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey)) { + if (Advapi32Util.registryValueExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language")) { + String installedLoc = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language"); + int lcid = Integer.parseInt(installedLoc); + char buf[] = new char[9]; + int cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO639LANGNAME, buf, 9); + String langCode = new String(buf, 0, cnt).trim().toLowerCase(); + + cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO3166CTRYNAME, buf, 9); + String countryCode = new String(buf, 0, cnt).trim().toLowerCase(); + + List langs=Arrays.asList(SelectLanguageDialog.getAvailableLanguages()); + for(int i=0;i. - */ -package com.sun.jna.platform.win32; - -/** - * - * @author JPEXS - */ -import com.sun.jna.Memory; -import com.sun.jna.Native; -import com.sun.jna.Pointer; -import com.sun.jna.platform.win32.WinNT.EVENTLOGRECORD; -import com.sun.jna.platform.win32.WinReg.HKEY; -import com.sun.jna.platform.win32.WinReg.HKEYByReference; -import com.sun.jna.ptr.IntByReference; -import java.util.ArrayList; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; - -/** - * Advapi32 utility API. - * - * @author dblock[at]dblock.org - */ -public abstract class Advapi32Util { - - /** - * An account. - */ - public static class Account { - - /** - * Account name. - */ - public String name; - /** - * Account domain. - */ - public String domain; - /** - * Account SID. - */ - public byte[] sid; - /** - * String representation of the account SID. - */ - public String sidString; - /** - * Account type, one of SID_NAME_USE. - */ - public int accountType; - /** - * Fully qualified account name. - */ - public String fqn; - } - - /** - * Checks whether a registry key exists. - * - * @param root HKEY_LOCAL_MACHINE, etc. - * @param key Path to the registry key. - * @return True if the key exists. - */ - public static boolean registryKeyExists(HKEY root, String key) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ, phkKey); - switch (rc) { - case W32Errors.ERROR_SUCCESS: - Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - return true; - case W32Errors.ERROR_FILE_NOT_FOUND: - return false; - default: - throw new Win32Exception(rc); - } - } - - /** - * Checks whether a registry value exists. - * - * @param root HKEY_LOCAL_MACHINE, etc. - * @param key Registry key path. - * @param value Value name. - * @return True if the value exists. - */ - public static boolean registryValueExists(HKEY root, String key, String value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ, phkKey); - try { - switch (rc) { - case W32Errors.ERROR_SUCCESS: - break; - case W32Errors.ERROR_FILE_NOT_FOUND: - return false; - default: - throw new Win32Exception(rc); - } - IntByReference lpcbData = new IntByReference(); - IntByReference lpType = new IntByReference(); - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); - switch (rc) { - case W32Errors.ERROR_SUCCESS: - case W32Errors.ERROR_INSUFFICIENT_BUFFER: - return true; - case W32Errors.ERROR_FILE_NOT_FOUND: - return false; - default: - throw new Win32Exception(rc); - } - } finally { - if (phkKey.getValue() != null && phkKey.getValue() != WinBase.INVALID_HANDLE_VALUE) { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - } - - /** - * Get a registry REG_SZ value. - * - * @param root Root key. - * @param key Registry path. - * @param value Name of the value to retrieve. - * @return String value. - */ - public static String registryGetStringValue(HKEY root, String key, String value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - IntByReference lpcbData = new IntByReference(); - IntByReference lpType = new IntByReference(); - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - if (lpType.getValue() != WinNT.REG_SZ) { - throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); - } - char[] data = new char[lpcbData.getValue()]; - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, data, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - return Native.toString(data); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Get a registry REG_EXPAND_SZ value. - * - * @param root Root key. - * @param key Registry path. - * @param value Name of the value to retrieve. - * @return String value. - */ - public static String registryGetExpandableStringValue(HKEY root, String key, String value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - IntByReference lpcbData = new IntByReference(); - IntByReference lpType = new IntByReference(); - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - if (lpType.getValue() != WinNT.REG_EXPAND_SZ) { - throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); - } - char[] data = new char[lpcbData.getValue()]; - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, data, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - return Native.toString(data); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Get a registry REG_MULTI_SZ value. - * - * @param root Root key. - * @param key Registry path. - * @param value Name of the value to retrieve. - * @return String value. - */ - public static String[] registryGetStringArray(HKEY root, String key, String value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - IntByReference lpcbData = new IntByReference(); - IntByReference lpType = new IntByReference(); - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - if (lpType.getValue() != WinNT.REG_MULTI_SZ) { - throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); - } - Memory data = new Memory(lpcbData.getValue()); - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, data, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - ArrayList result = new ArrayList<>(); - int offset = 0; - while (offset < data.size()) { - String s = data.getString(offset, true); - offset += s.length() * Native.WCHAR_SIZE; - offset += Native.WCHAR_SIZE; - result.add(s); - } - return result.toArray(new String[result.size()]); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Get a registry REG_BINARY value. - * - * @param root Root key. - * @param key Registry path. - * @param value Name of the value to retrieve. - * @return String value. - */ - public static byte[] registryGetBinaryValue(HKEY root, String key, String value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - IntByReference lpcbData = new IntByReference(); - IntByReference lpType = new IntByReference(); - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - if (lpType.getValue() != WinNT.REG_BINARY) { - throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_BINARY"); - } - byte[] data = new byte[lpcbData.getValue()]; - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, data, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - return data; - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Get a registry DWORD value. - * - * @param root Root key. - * @param key Registry key path. - * @param value Name of the value to retrieve. - * @return Integer value. - */ - public static int registryGetIntValue(HKEY root, String key, String value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - IntByReference lpcbData = new IntByReference(); - IntByReference lpType = new IntByReference(); - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - if (lpType.getValue() != WinNT.REG_DWORD) { - throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); - } - IntByReference data = new IntByReference(); - rc = Advapi32.INSTANCE.RegQueryValueEx( - phkKey.getValue(), value, 0, lpType, data, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { - throw new Win32Exception(rc); - } - return data.getValue(); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Create a registry key. - * - * @param hKey Parent key. - * @param keyName Key name. - * @return True if the key was created, false otherwise. - */ - public static boolean registryCreateKey(HKEY hKey, String keyName) { - HKEYByReference phkResult = new HKEYByReference(); - IntByReference lpdwDisposition = new IntByReference(); - int rc = Advapi32.INSTANCE.RegCreateKeyEx(hKey, keyName, 0, null, WinNT.REG_OPTION_NON_VOLATILE, - WinNT.KEY_READ, null, phkResult, lpdwDisposition); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - rc = Advapi32.INSTANCE.RegCloseKey(phkResult.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - return WinNT.REG_CREATED_NEW_KEY == lpdwDisposition.getValue(); - } - - /** - * Create a registry key. - * - * @param root Root key. - * @param parentPath Path to an existing registry key. - * @param keyName Key name. - * @return True if the key was created, false otherwise. - */ - public static boolean registryCreateKey(HKEY root, String parentPath, String keyName) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, parentPath, 0, WinNT.KEY_CREATE_SUB_KEY, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - return registryCreateKey(phkKey.getValue(), keyName); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Set an integer value in registry. - * - * @param hKey Parent key. - * @param name Value name. - * @param value Value to write to registry. - */ - public static void registrySetIntValue(HKEY hKey, String name, int value) { - byte[] data = new byte[4]; - data[0] = (byte) (value & 0xff); - data[1] = (byte) ((value >> 8) & 0xff); - data[2] = (byte) ((value >> 16) & 0xff); - data[3] = (byte) ((value >> 24) & 0xff); - int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_DWORD, data, 4); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - - /** - * Set an integer value in registry. - * - * @param root Root key. - * @param keyPath Path to an existing registry key. - * @param name Value name. - * @param value Value to write to registry. - */ - public static void registrySetIntValue(HKEY root, String keyPath, String name, int value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - registrySetIntValue(phkKey.getValue(), name, value); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Set a string value in registry. - * - * @param hKey Parent key. - * @param name Value name. - * @param value Value to write to registry. - */ - public static void registrySetStringValue(HKEY hKey, String name, String value) { - char[] data = Native.toCharArray(value); - int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_SZ, - data, data.length * Native.WCHAR_SIZE); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - - /** - * Set a string value in registry. - * - * @param root Root key. - * @param keyPath Path to an existing registry key. - * @param name Value name. - * @param value Value to write to registry. - */ - public static void registrySetStringValue(HKEY root, String keyPath, String name, String value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - registrySetStringValue(phkKey.getValue(), name, value); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Set an expandable string value in registry. - * - * @param hKey Parent key. - * @param name Value name. - * @param value Value to write to registry. - */ - public static void registrySetExpandableStringValue(HKEY hKey, String name, String value) { - char[] data = Native.toCharArray(value); - int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_EXPAND_SZ, - data, data.length * Native.WCHAR_SIZE); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - - /** - * Set a string value in registry. - * - * @param root Root key. - * @param keyPath Path to an existing registry key. - * @param name Value name. - * @param value Value to write to registry. - */ - public static void registrySetExpandableStringValue(HKEY root, String keyPath, String name, String value) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - registrySetExpandableStringValue(phkKey.getValue(), name, value); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Set a string array value in registry. - * - * @param hKey Parent key. - * @param name Name. - * @param arr Array of strings to write to registry. - */ - public static void registrySetStringArray(HKEY hKey, String name, String[] arr) { - int size = 0; - for (String s : arr) { - size += s.length() * Native.WCHAR_SIZE; - size += Native.WCHAR_SIZE; - } - - int offset = 0; - Memory data = new Memory(size); - for (String s : arr) { - data.setString(offset, s, true); - offset += s.length() * Native.WCHAR_SIZE; - offset += Native.WCHAR_SIZE; - } - - int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_MULTI_SZ, - data.getByteArray(0, size), size); - - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - - /** - * Set a string array value in registry. - * - * @param root Root key. - * @param keyPath Path to an existing registry key. - * @param name Value name. - * @param arr Array of strings to write to registry. - */ - public static void registrySetStringArray(HKEY root, String keyPath, String name, String[] arr) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - registrySetStringArray(phkKey.getValue(), name, arr); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Set a binary value in registry. - * - * @param hKey Parent key. - * @param name Value name. - * @param data Data to write to registry. - */ - public static void registrySetBinaryValue(HKEY hKey, String name, byte[] data) { - int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_BINARY, data, data.length); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - - /** - * Set a binary value in registry. - * - * @param root Root key. - * @param keyPath Path to an existing registry key. - * @param name Value name. - * @param data Data to write to registry. - */ - public static void registrySetBinaryValue(HKEY root, String keyPath, String name, byte[] data) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - registrySetBinaryValue(phkKey.getValue(), name, data); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Delete a registry key. - * - * @param hKey Parent key. - * @param keyName Name of the key to delete. - */ - public static void registryDeleteKey(HKEY hKey, String keyName) { - int rc = Advapi32.INSTANCE.RegDeleteKey(hKey, keyName); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - - /** - * Delete a registry key. - * - * @param root Root key. - * @param keyPath Path to an existing registry key. - * @param keyName Name of the key to delete. - */ - public static void registryDeleteKey(HKEY root, String keyPath, String keyName) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - registryDeleteKey(phkKey.getValue(), keyName); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Delete a registry value. - * - * @param hKey Parent key. - * @param valueName Name of the value to delete. - */ - public static void registryDeleteValue(HKEY hKey, String valueName) { - int rc = Advapi32.INSTANCE.RegDeleteValue(hKey, valueName); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - - /** - * Delete a registry value. - * - * @param root Root key. - * @param keyPath Path to an existing registry key. - * @param valueName Name of the value to delete. - */ - public static void registryDeleteValue(HKEY root, String keyPath, String valueName) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - registryDeleteValue(phkKey.getValue(), valueName); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Get names of the registry key's sub-keys. - * - * @param hKey Registry key. - * @return Array of registry key names. - */ - public static String[] registryGetKeys(HKEY hKey) { - IntByReference lpcSubKeys = new IntByReference(); - IntByReference lpcMaxSubKeyLen = new IntByReference(); - int rc = Advapi32.INSTANCE.RegQueryInfoKey(hKey, null, null, null, - lpcSubKeys, lpcMaxSubKeyLen, null, null, null, null, null, null); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - ArrayList keys = new ArrayList<>(lpcSubKeys.getValue()); - char[] name = new char[lpcMaxSubKeyLen.getValue() + 1]; - for (int i = 0; i < lpcSubKeys.getValue(); i++) { - IntByReference lpcchValueName = new IntByReference(lpcMaxSubKeyLen.getValue() + 1); - rc = Advapi32.INSTANCE.RegEnumKeyEx(hKey, i, name, lpcchValueName, - null, null, null, null); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - keys.add(Native.toString(name)); - } - return keys.toArray(new String[keys.size()]); - } - - /** - * Get names of the registry key's sub-keys. - * - * @param root Root key. - * @param keyPath Path to a registry key. - * @return Array of registry key names. - */ - public static String[] registryGetKeys(HKEY root, String keyPath) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - return registryGetKeys(phkKey.getValue()); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Get a table of registry values. - * - * @param hKey Registry key. - * @return Table of values. - */ - public static TreeMap registryGetValues(HKEY hKey) { - IntByReference lpcValues = new IntByReference(); - IntByReference lpcMaxValueNameLen = new IntByReference(); - IntByReference lpcMaxValueLen = new IntByReference(); - int rc = Advapi32.INSTANCE.RegQueryInfoKey(hKey, null, null, null, null, - null, null, lpcValues, lpcMaxValueNameLen, lpcMaxValueLen, null, null); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - TreeMap keyValues = new TreeMap<>(); - char[] name = new char[lpcMaxValueNameLen.getValue() + 1]; - byte[] data = new byte[lpcMaxValueLen.getValue()]; - for (int i = 0; i < lpcValues.getValue(); i++) { - IntByReference lpcchValueName = new IntByReference(lpcMaxValueNameLen.getValue() + 1); - IntByReference lpcbData = new IntByReference(lpcMaxValueLen.getValue()); - IntByReference lpType = new IntByReference(); - rc = Advapi32.INSTANCE.RegEnumValue(hKey, i, name, lpcchValueName, null, - lpType, data, lpcbData); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - - String nameString = Native.toString(name); - - Memory byteData = new Memory(lpcbData.getValue()); - byteData.write(0, data, 0, lpcbData.getValue()); - - switch (lpType.getValue()) { - case WinNT.REG_DWORD: { - keyValues.put(nameString, byteData.getInt(0)); - break; - } - case WinNT.REG_SZ: - case WinNT.REG_EXPAND_SZ: { - keyValues.put(nameString, byteData.getString(0, true)); - break; - } - case WinNT.REG_BINARY: { - keyValues.put(nameString, byteData.getByteArray(0, lpcbData.getValue())); - break; - } - case WinNT.REG_MULTI_SZ: { - Memory stringData = new Memory(lpcbData.getValue()); - stringData.write(0, data, 0, lpcbData.getValue()); - ArrayList result = new ArrayList<>(); - int offset = 0; - while (offset < stringData.size()) { - String s = stringData.getString(offset, true); - offset += s.length() * Native.WCHAR_SIZE; - offset += Native.WCHAR_SIZE; - result.add(s); - } - keyValues.put(nameString, result.toArray(new String[result.size()])); - break; - } - default: - throw new RuntimeException("Unsupported type: " + lpType.getValue()); - } - } - return keyValues; - } - - /** - * Get a table of registry values. - * - * @param root Registry root. - * @param keyPath Regitry key path. - * @return Table of values. - */ - public static TreeMap registryGetValues(HKEY root, String keyPath) { - HKEYByReference phkKey = new HKEYByReference(); - int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ, phkKey); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - try { - return registryGetValues(phkKey.getValue()); - } finally { - rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); - if (rc != W32Errors.ERROR_SUCCESS) { - throw new Win32Exception(rc); - } - } - } - - /** - * Converts a map of environment variables to an environment block suitable - * for {@link Advapi32#CreateProcessAsUser}. This environment block consists - * of null-terminated blocks of null-terminated strings. Each string is in - * the following form: name=value\0 - * - * @param environment Environment variables - * @return A environment block - */ - public static String getEnvironmentBlock(Map environment) { - StringBuilder out = new StringBuilder(); - for (Entry entry : environment.entrySet()) { - if (entry.getValue() != null) { - out.append(entry.getKey()).append("=").append(entry.getValue()).append("\0"); - } - } - return out.toString() + "\0"; - } - - /** - * Event log types. - */ - public static enum EventLogType { - - Error, - Warning, - Informational, - AuditSuccess, - AuditFailure - } - - /** - * An event log record. - */ - public static class EventLogRecord { - - private EVENTLOGRECORD _record = null; - private final String _source; - private byte[] _data; - private String[] _strings; - - /** - * Raw record data. - * - * @return EVENTLOGRECORD. - */ - public EVENTLOGRECORD getRecord() { - return _record; - } - - /** - * Event Id. - * - * @return Integer. - */ - public int getEventId() { - return _record.EventID.intValue(); - } - - /** - * Event source. - * - * @return String. - */ - public String getSource() { - return _source; - } - - /** - * Status code for the facility, part of the Event ID. - * - * @return Status code. - */ - public int getStatusCode() { - return _record.EventID.intValue() & 0xFFFF; - } - - /** - * Record number of the record. This value can be used with the - * EVENTLOG_SEEK_READ flag in the ReadEventLog function to begin reading - * at a specified record. - * - * @return Integer. - */ - public int getRecordNumber() { - return _record.RecordNumber.intValue(); - } - - /** - * Record length, with data. - * - * @return Number of bytes in the record including data. - */ - public int getLength() { - return _record.Length.intValue(); - } - - /** - * Strings associated with this event. - * - * @return Array of strings or null. - */ - public String[] getStrings() { - return _strings; - } - - /** - * Event log type. - * - * @return Event log type. - */ - public EventLogType getType() { - switch (_record.EventType.intValue()) { - case WinNT.EVENTLOG_SUCCESS: - case WinNT.EVENTLOG_INFORMATION_TYPE: - return EventLogType.Informational; - case WinNT.EVENTLOG_AUDIT_FAILURE: - return EventLogType.AuditFailure; - case WinNT.EVENTLOG_AUDIT_SUCCESS: - return EventLogType.AuditSuccess; - case WinNT.EVENTLOG_ERROR_TYPE: - return EventLogType.Error; - case WinNT.EVENTLOG_WARNING_TYPE: - return EventLogType.Warning; - default: - throw new RuntimeException("Invalid type: " + _record.EventType.intValue()); - } - } - - /** - * Raw data associated with the record. - * - * @return Array of bytes or null. - */ - public byte[] getData() { - return _data; - } - - public EventLogRecord(Pointer pevlr) { - _record = new EVENTLOGRECORD(pevlr); - _source = pevlr.getString(_record.size(), true); - // data - if (_record.DataLength.intValue() > 0) { - _data = pevlr.getByteArray(_record.DataOffset.intValue(), - _record.DataLength.intValue()); - } - // strings - if (_record.NumStrings.intValue() > 0) { - ArrayList strings = new ArrayList<>(); - int count = _record.NumStrings.intValue(); - long offset = _record.StringOffset.intValue(); - while (count > 0) { - String s = pevlr.getString(offset, true); - strings.add(s); - offset += s.length() * Native.WCHAR_SIZE; - offset += Native.WCHAR_SIZE; - count--; - } - _strings = strings.toArray(new String[strings.size()]); - } - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.sun.jna.platform.win32; + +/** + * + * @author JPEXS + */ +import com.sun.jna.Memory; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WinNT.EVENTLOGRECORD; +import com.sun.jna.platform.win32.WinReg.HKEY; +import com.sun.jna.platform.win32.WinReg.HKEYByReference; +import com.sun.jna.ptr.IntByReference; +import java.util.ArrayList; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +/** + * Advapi32 utility API. + * + * @author dblock[at]dblock.org + */ +public abstract class Advapi32Util { + + /** + * An account. + */ + public static class Account { + + /** + * Account name. + */ + public String name; + /** + * Account domain. + */ + public String domain; + /** + * Account SID. + */ + public byte[] sid; + /** + * String representation of the account SID. + */ + public String sidString; + /** + * Account type, one of SID_NAME_USE. + */ + public int accountType; + /** + * Fully qualified account name. + */ + public String fqn; + } + + /** + * Checks whether a registry key exists. + * + * @param root HKEY_LOCAL_MACHINE, etc. + * @param key Path to the registry key. + * @return True if the key exists. + */ + public static boolean registryKeyExists(HKEY root, String key) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); + switch (rc) { + case W32Errors.ERROR_SUCCESS: + Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + return true; + case W32Errors.ERROR_FILE_NOT_FOUND: + return false; + default: + throw new Win32Exception(rc); + } + } + + /** + * Checks whether a registry value exists. + * + * @param root HKEY_LOCAL_MACHINE, etc. + * @param key Registry key path. + * @param value Value name. + * @return True if the value exists. + */ + public static boolean registryValueExists(HKEY root, String key, String value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); + try { + switch (rc) { + case W32Errors.ERROR_SUCCESS: + break; + case W32Errors.ERROR_FILE_NOT_FOUND: + return false; + default: + throw new Win32Exception(rc); + } + IntByReference lpcbData = new IntByReference(); + IntByReference lpType = new IntByReference(); + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); + switch (rc) { + case W32Errors.ERROR_SUCCESS: + case W32Errors.ERROR_INSUFFICIENT_BUFFER: + return true; + case W32Errors.ERROR_FILE_NOT_FOUND: + return false; + default: + throw new Win32Exception(rc); + } + } finally { + if (phkKey.getValue() != null && phkKey.getValue() != WinBase.INVALID_HANDLE_VALUE) { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + } + + /** + * Get a registry REG_SZ value. + * + * @param root Root key. + * @param key Registry path. + * @param value Name of the value to retrieve. + * @return String value. + */ + public static String registryGetStringValue(HKEY root, String key, String value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + IntByReference lpcbData = new IntByReference(); + IntByReference lpType = new IntByReference(); + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + if (lpType.getValue() != WinNT.REG_SZ) { + throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); + } + char[] data = new char[lpcbData.getValue()]; + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, data, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + return Native.toString(data); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Get a registry REG_EXPAND_SZ value. + * + * @param root Root key. + * @param key Registry path. + * @param value Name of the value to retrieve. + * @return String value. + */ + public static String registryGetExpandableStringValue(HKEY root, String key, String value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + IntByReference lpcbData = new IntByReference(); + IntByReference lpType = new IntByReference(); + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + if (lpType.getValue() != WinNT.REG_EXPAND_SZ) { + throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); + } + char[] data = new char[lpcbData.getValue()]; + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, data, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + return Native.toString(data); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Get a registry REG_MULTI_SZ value. + * + * @param root Root key. + * @param key Registry path. + * @param value Name of the value to retrieve. + * @return String value. + */ + public static String[] registryGetStringArray(HKEY root, String key, String value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + IntByReference lpcbData = new IntByReference(); + IntByReference lpType = new IntByReference(); + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + if (lpType.getValue() != WinNT.REG_MULTI_SZ) { + throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); + } + Memory data = new Memory(lpcbData.getValue()); + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, data, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + ArrayList result = new ArrayList<>(); + int offset = 0; + while (offset < data.size()) { + String s = data.getString(offset, true); + offset += s.length() * Native.WCHAR_SIZE; + offset += Native.WCHAR_SIZE; + result.add(s); + } + return result.toArray(new String[result.size()]); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Get a registry REG_BINARY value. + * + * @param root Root key. + * @param key Registry path. + * @param value Name of the value to retrieve. + * @return String value. + */ + public static byte[] registryGetBinaryValue(HKEY root, String key, String value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + IntByReference lpcbData = new IntByReference(); + IntByReference lpType = new IntByReference(); + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + if (lpType.getValue() != WinNT.REG_BINARY) { + throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_BINARY"); + } + byte[] data = new byte[lpcbData.getValue()]; + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, data, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + return data; + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Get a registry DWORD value. + * + * @param root Root key. + * @param key Registry key path. + * @param value Name of the value to retrieve. + * @return Integer value. + */ + public static int registryGetIntValue(HKEY root, String key, String value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + IntByReference lpcbData = new IntByReference(); + IntByReference lpType = new IntByReference(); + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + if (lpType.getValue() != WinNT.REG_DWORD) { + throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); + } + IntByReference data = new IntByReference(); + rc = Advapi32.INSTANCE.RegQueryValueEx( + phkKey.getValue(), value, 0, lpType, data, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + return data.getValue(); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Create a registry key. + * + * @param hKey Parent key. + * @param keyName Key name. + * @return True if the key was created, false otherwise. + */ + public static boolean registryCreateKey(HKEY hKey, String keyName) { + HKEYByReference phkResult = new HKEYByReference(); + IntByReference lpdwDisposition = new IntByReference(); + int rc = Advapi32.INSTANCE.RegCreateKeyEx(hKey, keyName, 0, null, WinNT.REG_OPTION_NON_VOLATILE, + WinNT.KEY_READ, null, phkResult, lpdwDisposition); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + rc = Advapi32.INSTANCE.RegCloseKey(phkResult.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + return WinNT.REG_CREATED_NEW_KEY == lpdwDisposition.getValue(); + } + + /** + * Create a registry key. + * + * @param root Root key. + * @param parentPath Path to an existing registry key. + * @param keyName Key name. + * @return True if the key was created, false otherwise. + */ + public static boolean registryCreateKey(HKEY root, String parentPath, String keyName) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, parentPath, 0, WinNT.KEY_CREATE_SUB_KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + return registryCreateKey(phkKey.getValue(), keyName); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Set an integer value in registry. + * + * @param hKey Parent key. + * @param name Value name. + * @param value Value to write to registry. + */ + public static void registrySetIntValue(HKEY hKey, String name, int value) { + byte[] data = new byte[4]; + data[0] = (byte) (value & 0xff); + data[1] = (byte) ((value >> 8) & 0xff); + data[2] = (byte) ((value >> 16) & 0xff); + data[3] = (byte) ((value >> 24) & 0xff); + int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_DWORD, data, 4); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Set an integer value in registry. + * + * @param root Root key. + * @param keyPath Path to an existing registry key. + * @param name Value name. + * @param value Value to write to registry. + */ + public static void registrySetIntValue(HKEY root, String keyPath, String name, int value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + registrySetIntValue(phkKey.getValue(), name, value); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Set a string value in registry. + * + * @param hKey Parent key. + * @param name Value name. + * @param value Value to write to registry. + */ + public static void registrySetStringValue(HKEY hKey, String name, String value) { + char[] data = Native.toCharArray(value); + int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_SZ, + data, data.length * Native.WCHAR_SIZE); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Set a string value in registry. + * + * @param root Root key. + * @param keyPath Path to an existing registry key. + * @param name Value name. + * @param value Value to write to registry. + */ + public static void registrySetStringValue(HKEY root, String keyPath, String name, String value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + registrySetStringValue(phkKey.getValue(), name, value); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Set an expandable string value in registry. + * + * @param hKey Parent key. + * @param name Value name. + * @param value Value to write to registry. + */ + public static void registrySetExpandableStringValue(HKEY hKey, String name, String value) { + char[] data = Native.toCharArray(value); + int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_EXPAND_SZ, + data, data.length * Native.WCHAR_SIZE); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Set a string value in registry. + * + * @param root Root key. + * @param keyPath Path to an existing registry key. + * @param name Value name. + * @param value Value to write to registry. + */ + public static void registrySetExpandableStringValue(HKEY root, String keyPath, String name, String value) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + registrySetExpandableStringValue(phkKey.getValue(), name, value); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Set a string array value in registry. + * + * @param hKey Parent key. + * @param name Name. + * @param arr Array of strings to write to registry. + */ + public static void registrySetStringArray(HKEY hKey, String name, String[] arr) { + int size = 0; + for (String s : arr) { + size += s.length() * Native.WCHAR_SIZE; + size += Native.WCHAR_SIZE; + } + + int offset = 0; + Memory data = new Memory(size); + for (String s : arr) { + data.setString(offset, s, true); + offset += s.length() * Native.WCHAR_SIZE; + offset += Native.WCHAR_SIZE; + } + + int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_MULTI_SZ, + data.getByteArray(0, size), size); + + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Set a string array value in registry. + * + * @param root Root key. + * @param keyPath Path to an existing registry key. + * @param name Value name. + * @param arr Array of strings to write to registry. + */ + public static void registrySetStringArray(HKEY root, String keyPath, String name, String[] arr) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + registrySetStringArray(phkKey.getValue(), name, arr); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Set a binary value in registry. + * + * @param hKey Parent key. + * @param name Value name. + * @param data Data to write to registry. + */ + public static void registrySetBinaryValue(HKEY hKey, String name, byte[] data) { + int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_BINARY, data, data.length); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Set a binary value in registry. + * + * @param root Root key. + * @param keyPath Path to an existing registry key. + * @param name Value name. + * @param data Data to write to registry. + */ + public static void registrySetBinaryValue(HKEY root, String keyPath, String name, byte[] data) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + registrySetBinaryValue(phkKey.getValue(), name, data); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Delete a registry key. + * + * @param hKey Parent key. + * @param keyName Name of the key to delete. + */ + public static void registryDeleteKey(HKEY hKey, String keyName) { + int rc = Advapi32.INSTANCE.RegDeleteKey(hKey, keyName); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Delete a registry key. + * + * @param root Root key. + * @param keyPath Path to an existing registry key. + * @param keyName Name of the key to delete. + */ + public static void registryDeleteKey(HKEY root, String keyPath, String keyName) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + registryDeleteKey(phkKey.getValue(), keyName); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Delete a registry value. + * + * @param hKey Parent key. + * @param valueName Name of the value to delete. + */ + public static void registryDeleteValue(HKEY hKey, String valueName) { + int rc = Advapi32.INSTANCE.RegDeleteValue(hKey, valueName); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + + /** + * Delete a registry value. + * + * @param root Root key. + * @param keyPath Path to an existing registry key. + * @param valueName Name of the value to delete. + */ + public static void registryDeleteValue(HKEY root, String keyPath, String valueName) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + registryDeleteValue(phkKey.getValue(), valueName); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Get names of the registry key's sub-keys. + * + * @param hKey Registry key. + * @return Array of registry key names. + */ + public static String[] registryGetKeys(HKEY hKey) { + IntByReference lpcSubKeys = new IntByReference(); + IntByReference lpcMaxSubKeyLen = new IntByReference(); + int rc = Advapi32.INSTANCE.RegQueryInfoKey(hKey, null, null, null, + lpcSubKeys, lpcMaxSubKeyLen, null, null, null, null, null, null); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + ArrayList keys = new ArrayList<>(lpcSubKeys.getValue()); + char[] name = new char[lpcMaxSubKeyLen.getValue() + 1]; + for (int i = 0; i < lpcSubKeys.getValue(); i++) { + IntByReference lpcchValueName = new IntByReference(lpcMaxSubKeyLen.getValue() + 1); + rc = Advapi32.INSTANCE.RegEnumKeyEx(hKey, i, name, lpcchValueName, + null, null, null, null); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + keys.add(Native.toString(name)); + } + return keys.toArray(new String[keys.size()]); + } + + /** + * Get names of the registry key's sub-keys. + * + * @param root Root key. + * @param keyPath Path to a registry key. + * @return Array of registry key names. + */ + public static String[] registryGetKeys(HKEY root, String keyPath) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + return registryGetKeys(phkKey.getValue()); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Get a table of registry values. + * + * @param hKey Registry key. + * @return Table of values. + */ + public static TreeMap registryGetValues(HKEY hKey) { + IntByReference lpcValues = new IntByReference(); + IntByReference lpcMaxValueNameLen = new IntByReference(); + IntByReference lpcMaxValueLen = new IntByReference(); + int rc = Advapi32.INSTANCE.RegQueryInfoKey(hKey, null, null, null, null, + null, null, lpcValues, lpcMaxValueNameLen, lpcMaxValueLen, null, null); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + TreeMap keyValues = new TreeMap<>(); + char[] name = new char[lpcMaxValueNameLen.getValue() + 1]; + byte[] data = new byte[lpcMaxValueLen.getValue()]; + for (int i = 0; i < lpcValues.getValue(); i++) { + IntByReference lpcchValueName = new IntByReference(lpcMaxValueNameLen.getValue() + 1); + IntByReference lpcbData = new IntByReference(lpcMaxValueLen.getValue()); + IntByReference lpType = new IntByReference(); + rc = Advapi32.INSTANCE.RegEnumValue(hKey, i, name, lpcchValueName, null, + lpType, data, lpcbData); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + + String nameString = Native.toString(name); + + Memory byteData = new Memory(lpcbData.getValue()); + byteData.write(0, data, 0, lpcbData.getValue()); + + switch (lpType.getValue()) { + case WinNT.REG_DWORD: { + keyValues.put(nameString, byteData.getInt(0)); + break; + } + case WinNT.REG_SZ: + case WinNT.REG_EXPAND_SZ: { + keyValues.put(nameString, byteData.getString(0, true)); + break; + } + case WinNT.REG_BINARY: { + keyValues.put(nameString, byteData.getByteArray(0, lpcbData.getValue())); + break; + } + case WinNT.REG_MULTI_SZ: { + Memory stringData = new Memory(lpcbData.getValue()); + stringData.write(0, data, 0, lpcbData.getValue()); + ArrayList result = new ArrayList<>(); + int offset = 0; + while (offset < stringData.size()) { + String s = stringData.getString(offset, true); + offset += s.length() * Native.WCHAR_SIZE; + offset += Native.WCHAR_SIZE; + result.add(s); + } + keyValues.put(nameString, result.toArray(new String[result.size()])); + break; + } + default: + throw new RuntimeException("Unsupported type: " + lpType.getValue()); + } + } + return keyValues; + } + + /** + * Get a table of registry values. + * + * @param root Registry root. + * @param keyPath Regitry key path. + * @return Table of values. + */ + public static TreeMap registryGetValues(HKEY root, String keyPath) { + HKEYByReference phkKey = new HKEYByReference(); + int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ| WinNT.KEY_WOW64_32KEY, phkKey); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + try { + return registryGetValues(phkKey.getValue()); + } finally { + rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); + if (rc != W32Errors.ERROR_SUCCESS) { + throw new Win32Exception(rc); + } + } + } + + /** + * Converts a map of environment variables to an environment block suitable + * for {@link Advapi32#CreateProcessAsUser}. This environment block consists + * of null-terminated blocks of null-terminated strings. Each string is in + * the following form: name=value\0 + * + * @param environment Environment variables + * @return A environment block + */ + public static String getEnvironmentBlock(Map environment) { + StringBuilder out = new StringBuilder(); + for (Entry entry : environment.entrySet()) { + if (entry.getValue() != null) { + out.append(entry.getKey()).append("=").append(entry.getValue()).append("\0"); + } + } + return out.toString() + "\0"; + } + + /** + * Event log types. + */ + public static enum EventLogType { + + Error, + Warning, + Informational, + AuditSuccess, + AuditFailure + } + + /** + * An event log record. + */ + public static class EventLogRecord { + + private EVENTLOGRECORD _record = null; + private final String _source; + private byte[] _data; + private String[] _strings; + + /** + * Raw record data. + * + * @return EVENTLOGRECORD. + */ + public EVENTLOGRECORD getRecord() { + return _record; + } + + /** + * Event Id. + * + * @return Integer. + */ + public int getEventId() { + return _record.EventID.intValue(); + } + + /** + * Event source. + * + * @return String. + */ + public String getSource() { + return _source; + } + + /** + * Status code for the facility, part of the Event ID. + * + * @return Status code. + */ + public int getStatusCode() { + return _record.EventID.intValue() & 0xFFFF; + } + + /** + * Record number of the record. This value can be used with the + * EVENTLOG_SEEK_READ flag in the ReadEventLog function to begin reading + * at a specified record. + * + * @return Integer. + */ + public int getRecordNumber() { + return _record.RecordNumber.intValue(); + } + + /** + * Record length, with data. + * + * @return Number of bytes in the record including data. + */ + public int getLength() { + return _record.Length.intValue(); + } + + /** + * Strings associated with this event. + * + * @return Array of strings or null. + */ + public String[] getStrings() { + return _strings; + } + + /** + * Event log type. + * + * @return Event log type. + */ + public EventLogType getType() { + switch (_record.EventType.intValue()) { + case WinNT.EVENTLOG_SUCCESS: + case WinNT.EVENTLOG_INFORMATION_TYPE: + return EventLogType.Informational; + case WinNT.EVENTLOG_AUDIT_FAILURE: + return EventLogType.AuditFailure; + case WinNT.EVENTLOG_AUDIT_SUCCESS: + return EventLogType.AuditSuccess; + case WinNT.EVENTLOG_ERROR_TYPE: + return EventLogType.Error; + case WinNT.EVENTLOG_WARNING_TYPE: + return EventLogType.Warning; + default: + throw new RuntimeException("Invalid type: " + _record.EventType.intValue()); + } + } + + /** + * Raw data associated with the record. + * + * @return Array of bytes or null. + */ + public byte[] getData() { + return _data; + } + + public EventLogRecord(Pointer pevlr) { + _record = new EVENTLOGRECORD(pevlr); + _source = pevlr.getString(_record.size(), true); + // data + if (_record.DataLength.intValue() > 0) { + _data = pevlr.getByteArray(_record.DataOffset.intValue(), + _record.DataLength.intValue()); + } + // strings + if (_record.NumStrings.intValue() > 0) { + ArrayList strings = new ArrayList<>(); + int count = _record.NumStrings.intValue(); + long offset = _record.StringOffset.intValue(); + while (count > 0) { + String s = pevlr.getString(offset, true); + strings.add(s); + offset += s.length() * Native.WCHAR_SIZE; + offset += Native.WCHAR_SIZE; + count--; + } + _strings = strings.toArray(new String[strings.size()]); + } + } + } +} diff --git a/src/com/sun/jna/platform/win32/Kernel32.java b/src/com/sun/jna/platform/win32/Kernel32.java index 2730c4b2e..c0e7408cf 100644 --- a/src/com/sun/jna/platform/win32/Kernel32.java +++ b/src/com/sun/jna/platform/win32/Kernel32.java @@ -299,4 +299,9 @@ public interface Kernel32 extends WinNT { DWORD QueryDosDevice(String lpDeviceName, char[] lpTargetPath, int lenght); boolean VirtualProtectEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, int flNewProtect, IntByReference lpflOldProtect); + + + public static final int LOCALE_SISO3166CTRYNAME = 90; + public static final int LOCALE_SISO639LANGNAME = 89; + int GetLocaleInfo (int Locale, int LCType, char[] lpLCData, int cchData); }