1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package com.sun.star.lib.loader;
25 
26 import java.io.BufferedInputStream;
27 import java.io.BufferedOutputStream;
28 import java.io.File;
29 import java.io.FileOutputStream;
30 import java.io.InputStream;
31 
32 
33 /**
34  * This class provides functionality for reading string values from the
35  * Windows Registry. It requires the native library unowinreg.dll.
36  */
37 final class WinRegKey {
38 
39     private String m_rootKeyName;
40     private String m_subKeyName;
41 
42     // native methods to access the windows registry
winreg_RegOpenClassesRoot( long[] hkresult )43     private static native boolean winreg_RegOpenClassesRoot( long[] hkresult );
winreg_RegOpenCurrentConfig( long[] hkresult )44     private static native boolean winreg_RegOpenCurrentConfig(
45         long[] hkresult );
winreg_RegOpenCurrentUser( long[] hkresult )46     private static native boolean winreg_RegOpenCurrentUser( long[] hkresult );
winreg_RegOpenLocalMachine( long[] hkresult )47     private static native boolean winreg_RegOpenLocalMachine( long[] hkresult );
winreg_RegOpenUsers( long[] hkresult )48     private static native boolean winreg_RegOpenUsers( long[] hkresult );
winreg_RegOpenKeyEx( long parent, String name, long[] hkresult )49     private static native boolean winreg_RegOpenKeyEx( long parent, String name,
50         long[] hkresult );
winreg_RegCloseKey( long hkey )51     private static native boolean winreg_RegCloseKey( long hkey );
winreg_RegQueryValueEx( long hkey, String value, long[] type, byte[] data, long[] size )52     private static native boolean winreg_RegQueryValueEx(
53         long hkey, String value, long[] type,
54         byte[] data, long[] size );
winreg_RegQueryInfoKey( long hkey, long[] subkeys, long[] maxSubkeyLen, long[] values, long[] maxValueNameLen, long[] maxValueLen, long[] secDescriptor )55     private static native boolean winreg_RegQueryInfoKey(
56         long hkey, long[] subkeys, long[] maxSubkeyLen,
57         long[] values, long[] maxValueNameLen,
58         long[] maxValueLen, long[] secDescriptor );
59 
60     // load the native library unowinreg.dll
61     static {
62         try {
63             ClassLoader cl = WinRegKey.class.getClassLoader();
64             InputStream is = cl.getResourceAsStream( "win/unowinreg.dll" );
65             if ( is != null ) {
66                 // generate a temporary name for lib file and write to temp
67                 // location
68                 BufferedInputStream istream = new BufferedInputStream( is );
69                 File libfile = File.createTempFile( "unowinreg", ".dll" );
libfile.deleteOnExit()70                 libfile.deleteOnExit(); // ensure deletion
71                 BufferedOutputStream ostream = new BufferedOutputStream(
72                     new FileOutputStream( libfile ) );
73                 int bsize = 2048; int n = 0;
74                 byte[] buffer = new byte[bsize];
75                 while ( ( n = istream.read( buffer, 0, bsize ) ) != -1 ) {
ostream.write( buffer, 0, n )76                     ostream.write( buffer, 0, n );
77                 }
istream.close()78                 istream.close();
ostream.close()79                 ostream.close();
80                 // load library
libfile.getPath()81                 System.load( libfile.getPath() );
82             } else {
83                 // If the library cannot be found as a class loader resource,
84                 // try the global System.loadLibrary(). The JVM will look for
85                 // it in the java.library.path.
86                 System.loadLibrary( "unowinreg" );
87             }
88         } catch ( java.lang.Exception e ) {
89             System.err.println( "com.sun.star.lib.loader.WinRegKey: " +
90                 "loading of native library failed!" + e );
91         }
92     }
93 
94     /**
95      * Constructs a <code>WinRegKey</code>.
96      */
WinRegKey( String rootKeyName, String subKeyName )97     public WinRegKey( String rootKeyName, String subKeyName ) {
98         m_rootKeyName = rootKeyName;
99         m_subKeyName = subKeyName;
100     }
101 
102     /**
103      * Reads a string value for the specified value name.
104      */
getStringValue( String valueName )105     public String getStringValue( String valueName ) throws WinRegKeyException {
106         byte[] data = getValue( valueName );
107         // remove terminating null character
108         return new String( data, 0, data.length - 1 );
109     }
110 
111     /**
112      * Reads a value for the specified value name.
113      */
getValue( String valueName )114     private byte[] getValue( String valueName ) throws WinRegKeyException {
115 
116         byte[] result = null;
117         long[] hkey = {0};
118 
119         // open the specified registry key
120         boolean bRet = false;
121         long[] hroot = {0};
122         if ( m_rootKeyName.equals( "HKEY_CLASSES_ROOT" ) ) {
123             bRet = winreg_RegOpenClassesRoot( hroot );
124         } else if ( m_rootKeyName.equals( "HKEY_CURRENT_CONFIG" ) ) {
125             bRet = winreg_RegOpenCurrentConfig( hroot );
126         } else if ( m_rootKeyName.equals( "HKEY_CURRENT_USER" ) ) {
127             bRet = winreg_RegOpenCurrentUser( hroot );
128         } else if ( m_rootKeyName.equals( "HKEY_LOCAL_MACHINE" ) ) {
129             bRet = winreg_RegOpenLocalMachine( hroot );
130         } else if ( m_rootKeyName.equals( "HKEY_USERS" ) ) {
131             bRet = winreg_RegOpenUsers( hroot );
132         } else {
133             throw new WinRegKeyException( "unknown root registry key!");
134         }
135         if ( !bRet ) {
136             throw new WinRegKeyException( "opening root registry key " +
137                 "failed!" );
138         }
139         if ( !winreg_RegOpenKeyEx( hroot[0], m_subKeyName, hkey ) ) {
140             if ( !winreg_RegCloseKey( hroot[0] ) ) {
141                 throw new WinRegKeyException( "opening registry key and " +
142                     "releasing root registry key handle failed!" );
143             }
144             throw new WinRegKeyException( "opening registry key failed!" );
145         }
146 
147         // get the size of the longest data component among the key's values
148         long[] subkeys = {0};
149         long[] maxSubkeyLen = {0};
150         long[] values = {0};
151         long[] maxValueNameLen = {0};
152         long[] maxValueLen = {0};
153         long[] secDescriptor = {0};
154         if ( !winreg_RegQueryInfoKey( hkey[0], subkeys, maxSubkeyLen,
155                  values, maxValueNameLen, maxValueLen, secDescriptor ) ) {
156             if ( !winreg_RegCloseKey( hkey[0] ) ||
157                  !winreg_RegCloseKey( hroot[0] ) ) {
158                 throw new WinRegKeyException( "retrieving information about " +
159                     "the registry key and releasing registry key handles " +
160                     "failed!" );
161             }
162             throw new WinRegKeyException( "retrieving information about " +
163                 "the registry key failed!" );
164         }
165 
166         // get the data for the specified value name
167         byte[] buffer = new byte[ (int) maxValueLen[0] ];
168         long[] size = new long[1];
169         size[0] = buffer.length;
170         long[] type = new long[1];
171         type[0] = 0;
172         if ( !winreg_RegQueryValueEx( hkey[0], valueName, type, buffer,
173                  size ) ) {
174             if ( !winreg_RegCloseKey( hkey[0] ) ||
175                  !winreg_RegCloseKey( hroot[0] ) ) {
176                 throw new WinRegKeyException( "retrieving data for the " +
177                     "specified value name and releasing registry key handles " +
178                     "failed!" );
179             }
180             throw new WinRegKeyException( "retrieving data for the " +
181                 "specified value name failed!" );
182         }
183 
184         // release registry key handles
185         if ( !winreg_RegCloseKey( hkey[0] ) ||
186              !winreg_RegCloseKey( hroot[0] ) ) {
187             throw new WinRegKeyException( "releasing registry key handles " +
188                 "failed!" );
189         }
190 
191         result = new byte[ (int) size[0] ];
192         System.arraycopy( buffer, 0, result, 0, (int)size[0] );
193 
194         return result;
195     }
196 }
197