View Javadoc

1   /*
2    * Copyright 2004-2008 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.uruma.util.win32;
17  
18  import java.io.StringWriter;
19  import java.nio.ByteBuffer;
20  import java.nio.ByteOrder;
21  
22  import nlink.Holder;
23  import nlink.win32.NLink;
24  
25  import org.eclipse.swt.SWT;
26  import org.eclipse.swt.graphics.Image;
27  import org.eclipse.swt.graphics.ImageData;
28  import org.eclipse.swt.internal.win32.OS;
29  import org.eclipse.swt.internal.win32.SHFILEINFO;
30  import org.eclipse.swt.internal.win32.SHFILEINFOA;
31  import org.eclipse.swt.internal.win32.SHFILEINFOW;
32  import org.eclipse.swt.internal.win32.TCHAR;
33  import org.seasar.uruma.exception.Win32ApiException;
34  import org.seasar.uruma.util.AssertionUtil;
35  
36  /**
37   * Java から Win32 API を呼び出すためのユーティリティクラスです。<br />
38   * 
39   * @author y-komori
40   */
41  public class Win32API {
42      protected static final int MAX_COMPUTERNAME_LENGTH = 15;
43  
44      private static Kernel32 kernel32 = NLink.create(Kernel32.class);
45  
46      private Win32API() {
47  
48      }
49  
50      private static final int SHGFI_TYPENAME = 1024;
51  
52      private static final int SHGFI_DISPLAYNAME = 512;
53  
54      /**
55       * ローカルコンピュータの NetBIOS 名を取得します。<br />
56       * 
57       * @return ローカルコンピュータのNetBIOS名
58       */
59      public static String getComputerName() {
60          ByteBuffer buffer = ByteBuffer
61                  .allocateDirect(MAX_COMPUTERNAME_LENGTH + 1);
62          Holder<Integer> holder = new Holder<Integer>(buffer.capacity());
63  
64          try {
65              kernel32.GetComputerName(buffer, holder);
66              return convertToJavaString(buffer);
67          } catch (Exception ex) {
68              throw new Win32ApiException(ex.getLocalizedMessage());
69          }
70      }
71  
72      /**
73       * 現在利用可能なディスクドライブを取得します。<br />
74       * 
75       * @return 利用可能なディスクドライブ名の配列
76       */
77      public static String[] getLogicalDrives() {
78          try {
79              int result = kernel32.GetLogicalDrives();
80  
81              int mask = 0x01;
82              int cnt = 0;
83              for (int i = 0; i < 26; i++, mask = mask << 1) {
84                  if ((result & mask) != 0) {
85                      cnt++;
86                  }
87              }
88              String[] drives = new String[cnt];
89              char drive = 'A';
90              mask = 0x01;
91              cnt = 0;
92              for (int i = 0; i < 26; i++, drive++, mask = mask << 1) {
93                  if ((result & mask) != 0) {
94                      drives[cnt++] = drive + ":\\";
95                  }
96              }
97              return drives;
98  
99          } catch (Exception ex) {
100             throw new Win32ApiException(ex.getLocalizedMessage());
101         }
102     }
103 
104     /**
105      * ボリューム情報を取得します。<br />
106      * 
107      * @param rootPathName
108      *            ボリュームのルートパス
109      * @return ボリューム情報。取得できなかった場合は <code>null</code>
110      */
111     public static VolumeInformation getVolumeInformation(
112             final String rootPathName) {
113         ByteBuffer volumeNameBuf = ByteBuffer.allocateDirect(128);
114         Holder<Integer> volumeSerialNum = new Holder<Integer>(new Integer(0));
115         Holder<Integer> maxComponentLength = new Holder<Integer>(new Integer(0));
116         Holder<Integer> fileSystemFlags = new Holder<Integer>(new Integer(0));
117         ByteBuffer fileSystemNameBuf = ByteBuffer.allocateDirect(128);
118 
119         try {
120             kernel32.SetErrorMode(Kernel32.SEM_FAILCRITICALERRORS);
121             int result = kernel32.GetVolumeInformation(rootPathName,
122                     volumeNameBuf, volumeNameBuf.capacity(), volumeSerialNum,
123                     maxComponentLength, fileSystemFlags, fileSystemNameBuf,
124                     fileSystemNameBuf.capacity());
125             if (result != 0) {
126                 VolumeInformation info = new VolumeInformation();
127                 info.setRootPath(rootPathName);
128                 info.setVolumeLabel(convertToJavaString(volumeNameBuf));
129                 info.setSerialNumber(volumeSerialNum.value);
130                 info.setFileSystemName(convertToJavaString(fileSystemNameBuf));
131                 info.setMaxComponentLength(maxComponentLength.value);
132                 info.setFileSystemFlags(fileSystemFlags.value);
133                 return info;
134             } else {
135                 return null;
136             }
137         } catch (Exception ex) {
138             throw new Win32ApiException(ex.getLocalizedMessage());
139         }
140     }
141 
142     /**
143      * 指定したルートパスのドライブの種類を調べます。<br />
144      * 
145      * @param rootPathName
146      *            種類を調べるドライブのルートパス
147      * @return ドライブの種類
148      * @see DriveType
149      */
150     public static DriveType getDriveType(final String rootPathName) {
151         try {
152             int result = kernel32.GetDriveType(rootPathName);
153 
154             switch (result) {
155             case Kernel32.DRIVE_UNKNOWN:
156                 return DriveType.DRIVE_UNKNOWN;
157 
158             case Kernel32.DRIVE_NO_ROOT_DIR:
159                 return DriveType.DRIVE_NO_ROOT_DIR;
160 
161             case Kernel32.DRIVE_REMOVABLE:
162                 return DriveType.DRIVE_REMOVABLE;
163 
164             case Kernel32.DRIVE_FIXED:
165                 return DriveType.DRIVE_FIXED;
166 
167             case Kernel32.DRIVE_REMOTE:
168                 return DriveType.DRIVE_REMOTE;
169 
170             case Kernel32.DRIVE_CDROM:
171                 return DriveType.DRIVE_CDROM;
172 
173             case Kernel32.DRIVE_RAMDISK:
174                 return DriveType.DRIVE_RAMDISK;
175 
176             default:
177                 return DriveType.DRIVE_UNKNOWN;
178             }
179         } catch (Exception ex) {
180             throw new Win32ApiException(ex.getLocalizedMessage());
181         }
182     }
183 
184     /**
185      * 指定されたファイルの種類を取得します。<br />
186      * 
187      * @param path
188      *            種類を調べるファイルのパス
189      * @return ファイルの種類
190      */
191     public static String getFileTypeName(final String path) {
192         int flags = SHGFI_TYPENAME | OS.SHGFI_USEFILEATTRIBUTES;
193         SHFILEINFO info = getFileInfo(path, flags);
194         if (info instanceof SHFILEINFOW) {
195             return convertToJavaString(((SHFILEINFOW) info).szTypeName);
196         } else {
197             return convertToJavaString(((SHFILEINFOA) info).szTypeName);
198         }
199     }
200 
201     /**
202      * 指定されたファイルの表示名称を取得します。<br />
203      * 
204      * @param path
205      *            ファイルのパス
206      * @return 表示名称
207      */
208     public static String getFileDisplayName(final String path) {
209         int flags = SHGFI_DISPLAYNAME | OS.SHGFI_USEFILEATTRIBUTES;
210         SHFILEINFO info = getFileInfo(path, flags);
211         if (info instanceof SHFILEINFOW) {
212             return convertToJavaString(((SHFILEINFOW) info).szDisplayName);
213         } else {
214             return convertToJavaString(((SHFILEINFOA) info).szDisplayName);
215         }
216     }
217 
218     /**
219      * 指定したパスのアイコンをを取得します。<br />
220      * 
221      * @param path
222      *            パス
223      * @return アイコンの {@link ImageData} オブジェクト
224      */
225     public static ImageData getFileIcon(final String path) {
226         int flags = OS.SHGFI_ICON | OS.SHGFI_SMALLICON
227                 | OS.SHGFI_USEFILEATTRIBUTES;
228         SHFILEINFO info = getFileInfo(path, flags);
229         if (info.hIcon != 0) {
230             Image image = Image.win32_new(null, SWT.ICON, info.hIcon);
231             ImageData imageData = image.getImageData();
232             image.dispose();
233             return imageData;
234         } else {
235             return null;
236         }
237     }
238 
239     private static SHFILEINFO getFileInfo(final String path, final int flags) {
240         AssertionUtil.assertNotNull("path", path);
241         SHFILEINFO info = OS.IsUnicode ? (SHFILEINFO) new SHFILEINFOW()
242                 : new SHFILEINFOA();
243         TCHAR pszPath = new TCHAR(0, path, true);
244         int retCode = OS.SHGetFileInfo(pszPath, OS.FILE_ATTRIBUTE_NORMAL, info,
245                 SHFILEINFO.sizeof, flags);
246         if (retCode != 0) {
247             return info;
248         } else {
249             throw new Win32ApiException("SHGetFileInfo", retCode);
250         }
251     }
252 
253     /**
254      * ファイルからインデックスで指定したアイコンを取得します。<br />
255      * 
256      * @param fileName
257      *            ファイル名
258      * @param index
259      *            アイコンのインデックス番号
260      * @return アイコンの {@link ImageData} オブジェクト
261      */
262     public static ImageData extractIcon(final String fileName, final int index) {
263         TCHAR lpszFile = new TCHAR(0, fileName, true);
264         int[] phiconSmall = new int[1];
265         int[] phiconLarge = null;
266         OS.ExtractIconEx(lpszFile, index, phiconLarge, phiconSmall, 1);
267         if (phiconSmall[0] == 0) {
268             return null;
269         }
270         Image image = Image.win32_new(null, SWT.ICON, phiconSmall[0]);
271         ImageData imageData = image.getImageData();
272         image.dispose();
273         return imageData;
274     }
275 
276     /**
277      * 指定した文字列に含まれる環境変数を展開します。<br />
278      * 
279      * @param str
280      *            対象文字列
281      * @return 環境変数展開後の文字列
282      */
283     public static String expandEnvironmentStrings(final String str) {
284         TCHAR lpSrc = new TCHAR(OS.CP_INSTALLED, str, true);
285         String result = str;
286         int length = OS.ExpandEnvironmentStrings(lpSrc, null, 0);
287         if (length != 0) {
288             TCHAR lpDst = new TCHAR(0, length);
289             OS.ExpandEnvironmentStrings(lpSrc, lpDst, length);
290             result = lpDst.toString(0, Math.max(0, length - 1));
291         }
292         return result;
293     }
294 
295     static String convertToJavaString(final ByteBuffer buffer) {
296         buffer.order(ByteOrder.LITTLE_ENDIAN);
297         StringWriter writer = new StringWriter();
298         for (int i = 0; buffer.remaining() > 0; i++) {
299             short chr = buffer.getShort();
300             if (chr == 0x00) {
301                 break;
302             } else {
303                 writer.write(chr);
304             }
305         }
306         writer.flush();
307         return writer.toString();
308     }
309 
310     static String convertToJavaString(final char[] str) {
311         StringWriter writer = new StringWriter();
312         for (int i = 0; i < str.length; i++) {
313             if (str[i] == 0x00) {
314                 break;
315             } else {
316                 writer.write(str[i]);
317             }
318         }
319         writer.flush();
320         return writer.toString();
321     }
322 
323     static String convertToJavaString(final byte[] bytes) {
324         byte[] result = null;
325         for (int i = 0; i < bytes.length; i++) {
326             if (bytes[i] == 0x00) {
327                 result = new byte[i];
328                 System.arraycopy(bytes, 0, result, 0, result.length);
329                 return new String(result);
330             }
331         }
332         return "";
333     }
334 }