1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package com.sun.star.lib.loader;
29 
30 import java.io.BufferedInputStream;
31 import java.io.BufferedOutputStream;
32 import java.io.File;
33 import java.io.FileOutputStream;
34 import java.io.InputStream;
35 
36 
37 /**
38  * This class provides functionality for reading string values from the
39  * Windows Registry. It requires the native library unowinreg.dll.
40  */
41 final class WinRegKey {
42 
43     private String m_rootKeyName;
44     private String m_subKeyName;
45 
46     // native methods to access the windows registry
47     private static native boolean winreg_RegOpenClassesRoot( long[] hkresult );
48     private static native boolean winreg_RegOpenCurrentConfig(
49         long[] hkresult );
50     private static native boolean winreg_RegOpenCurrentUser( long[] hkresult );
51     private static native boolean winreg_RegOpenLocalMachine( long[] hkresult );
52     private static native boolean winreg_RegOpenUsers( long[] hkresult );
53     private static native boolean winreg_RegOpenKeyEx( long parent, String name,
54         long[] hkresult );
55     private static native boolean winreg_RegCloseKey( long hkey );
56     private static native boolean winreg_RegQueryValueEx(
57         long hkey, String value, long[] type,
58         byte[] data, long[] size );
59     private static native boolean winreg_RegQueryInfoKey(
60         long hkey, long[] subkeys, long[] maxSubkeyLen,
61         long[] values, long[] maxValueNameLen,
62         long[] maxValueLen, long[] secDescriptor );
63 
64     // load the native library unowinreg.dll
65     static {
66         try {
67             ClassLoader cl = WinRegKey.class.getClassLoader();
68             InputStream is = cl.getResourceAsStream( "win/unowinreg.dll" );
69             if ( is != null ) {
70                 // generate a temporary name for lib file and write to temp
71                 // location
72                 BufferedInputStream istream = new BufferedInputStream( is );
73                 File libfile = File.createTempFile( "unowinreg", ".dll" );
74                 libfile.deleteOnExit(); // ensure deletion
75                 BufferedOutputStream ostream = new BufferedOutputStream(
76                     new FileOutputStream( libfile ) );
77                 int bsize = 2048; int n = 0;
78                 byte[] buffer = new byte[bsize];
79                 while ( ( n = istream.read( buffer, 0, bsize ) ) != -1 ) {
80                     ostream.write( buffer, 0, n );
81                 }
82                 istream.close();
83                 ostream.close();
84                 // load library
85                 System.load( libfile.getPath() );
86             } else {
87                 // If the library cannot be found as a class loader resource,
88                 // try the global System.loadLibrary(). The JVM will look for
89                 // it in the java.library.path.
90                 System.loadLibrary( "unowinreg" );
91             }
92         } catch ( java.lang.Exception e ) {
93             System.err.println( "com.sun.star.lib.loader.WinRegKey: " +
94                 "loading of native library failed!" + e );
95         }
96     }
97 
98     /**
99      * Constructs a <code>WinRegKey</code>.
100      */
101     public WinRegKey( String rootKeyName, String subKeyName ) {
102         m_rootKeyName = rootKeyName;
103         m_subKeyName = subKeyName;
104     }
105 
106     /**
107      * Reads a string value for the specified value name.
108      */
109     public String getStringValue( String valueName ) throws WinRegKeyException {
110         byte[] data = getValue( valueName );
111         // remove terminating null character
112         return new String( data, 0, data.length - 1 );
113     }
114 
115     /**
116      * Reads a value for the specified value name.
117      */
118     private byte[] getValue( String valueName ) throws WinRegKeyException {
119 
120         byte[] result = null;
121         long[] hkey = {0};
122 
123         // open the specified registry key
124         boolean bRet = false;
125         long[] hroot = {0};
126         if ( m_rootKeyName.equals( "HKEY_CLASSES_ROOT" ) ) {
127             bRet = winreg_RegOpenClassesRoot( hroot );
128         } else if ( m_rootKeyName.equals( "HKEY_CURRENT_CONFIG" ) ) {
129             bRet = winreg_RegOpenCurrentConfig( hroot );
130         } else if ( m_rootKeyName.equals( "HKEY_CURRENT_USER" ) ) {
131             bRet = winreg_RegOpenCurrentUser( hroot );
132         } else if ( m_rootKeyName.equals( "HKEY_LOCAL_MACHINE" ) ) {
133             bRet = winreg_RegOpenLocalMachine( hroot );
134         } else if ( m_rootKeyName.equals( "HKEY_USERS" ) ) {
135             bRet = winreg_RegOpenUsers( hroot );
136         } else {
137             throw new WinRegKeyException( "unknown root registry key!");
138         }
139         if ( !bRet ) {
140             throw new WinRegKeyException( "opening root registry key " +
141                 "failed!" );
142         }
143         if ( !winreg_RegOpenKeyEx( hroot[0], m_subKeyName, hkey ) ) {
144             if ( !winreg_RegCloseKey( hroot[0] ) ) {
145                 throw new WinRegKeyException( "opening registry key and " +
146                     "releasing root registry key handle failed!" );
147             }
148             throw new WinRegKeyException( "opening registry key failed!" );
149         }
150 
151         // get the size of the longest data component among the key's values
152         long[] subkeys = {0};
153         long[] maxSubkeyLen = {0};
154         long[] values = {0};
155         long[] maxValueNameLen = {0};
156         long[] maxValueLen = {0};
157         long[] secDescriptor = {0};
158         if ( !winreg_RegQueryInfoKey( hkey[0], subkeys, maxSubkeyLen,
159                  values, maxValueNameLen, maxValueLen, secDescriptor ) ) {
160             if ( !winreg_RegCloseKey( hkey[0] ) ||
161                  !winreg_RegCloseKey( hroot[0] ) ) {
162                 throw new WinRegKeyException( "retrieving information about " +
163                     "the registry key and releasing registry key handles " +
164                     "failed!" );
165             }
166             throw new WinRegKeyException( "retrieving information about " +
167                 "the registry key failed!" );
168         }
169 
170         // get the data for the specified value name
171         byte[] buffer = new byte[ (int) maxValueLen[0] ];
172         long[] size = new long[1];
173         size[0] = buffer.length;
174         long[] type = new long[1];
175         type[0] = 0;
176         if ( !winreg_RegQueryValueEx( hkey[0], valueName, type, buffer,
177                  size ) ) {
178             if ( !winreg_RegCloseKey( hkey[0] ) ||
179                  !winreg_RegCloseKey( hroot[0] ) ) {
180                 throw new WinRegKeyException( "retrieving data for the " +
181                     "specified value name and releasing registry key handles " +
182                     "failed!" );
183             }
184             throw new WinRegKeyException( "retrieving data for the " +
185                 "specified value name failed!" );
186         }
187 
188         // release registry key handles
189         if ( !winreg_RegCloseKey( hkey[0] ) ||
190              !winreg_RegCloseKey( hroot[0] ) ) {
191             throw new WinRegKeyException( "releasing registry key handles " +
192                 "failed!" );
193         }
194 
195         result = new byte[ (int) size[0] ];
196         System.arraycopy( buffer, 0, result, 0, (int)size[0] );
197 
198         return result;
199     }
200 }
201