Introduction
之前曾study過WinAPI去新增Share資料夾與刪除Share資料夾。基於不想使用呼叫外部程式的方式,選擇透過JNA去達到我的需求。而4.1.0的JNA還沒實作我想要的這些功能,就自己來搞定了。
How to?
首先實作存取共享資訊的結構SHARE_INFO_2,除了這個外,其餘的可以參考link。你可以根據需求去實作你所需要的。
package org.tonylin.util.jna; import java.util.Arrays; import java.util.List; import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.WString; /** * @see https://msdn.microsoft.com/en-us/library/bb525408(v=vs.85).aspx * @author TonyLin */ public class SHARE_INFO_2 extends Structure { class ByReference implements Structure.ByReference { } public WString shi2_netname; public int shi2_type; public WString shi2_remark; public int shi2_permissions; public int shi2_max_uses; public int shi2_current_uses; public WString shi2_path; public WString shi2_passwd; public SHARE_INFO_2(){ } public SHARE_INFO_2(Pointer p){ super(p); } @Override protected List getFieldOrder() { return Arrays.asList("shi2_netname", "shi2_type", "shi2_remark", "shi2_permissions", "shi2_max_uses", "shi2_current_uses", "shi2_path", "shi2_passwd"); } }
我們所需要的API都在Netapi32函式庫中,我們基於原本JNA已有的Netapi32去擴充:
package org.tonylin.util.jna; import com.sun.jna.Native; import com.sun.jna.WString; import com.sun.jna.platform.win32.Netapi32; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; import com.sun.jna.win32.W32APIOptions; /** * @see https://msdn.microsoft.com/en-us/library/bb525393(v=vs.85).aspx * @author TonyLin */ public interface Netapi32Ext extends Netapi32 { Netapi32Ext INSTANCE = (Netapi32Ext) Native.loadLibrary("Netapi32", Netapi32Ext.class, W32APIOptions.UNICODE_OPTIONS); /** * @see https://msdn.microsoft.com/en-us/library/bb525384(v=vs.85).aspx * * @param servername * @param level * @param buf * @param parm_err * @return */ public int NetShareAdd(String servername, int level, SHARE_INFO_2 buf, IntByReference parm_err); /** * @see https://msdn.microsoft.com/en-us/library/bb525386(v=vs.85).aspx * * @param servername * @param device * @param reserved * @return */ public int NetShareDel(WString servername, WString device, int reserved); /** * @see https://msdn.microsoft.com/en-us/library/bb525388(v=vs.85).aspx * * @param servername * @param netname * @param level * @param bufptr * @return */ public int NetShareGetInfo(WString servername, WString netname, int level, PointerByReference bufptr); }
Unit Test
針對新增、刪除與查詢做測試,必須使用admin的權限去啟動eclipse,才能正常執行。
package org.tonylin.util.jna; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.io.File; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.tonylin.util.io.FileUtil; import com.sun.jna.WString; import com.sun.jna.platform.win32.Kernel32Util; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; public class Netapi32ExtTest { private String sharedFolder = "/TEST_SHARE"; private File shareFolder = new File(sharedFolder); static private String SHARE_NAME = "TEST_SHARE"; @Before public void setup() { FileUtil.createFolder(sharedFolder); } @After public void teardown() { Netapi32Ext.INSTANCE.NetShareDel(null, new WString( SHARE_NAME), 0); FileUtil.deleteFile(sharedFolder); } @Test public void testNetShareGetInfo() { System.out.println("-> testNetShareGetInfo"); PointerByReference buf = new PointerByReference(); try { int ret = Netapi32Ext.INSTANCE.NetShareGetInfo(null, new WString( SHARE_NAME), 2, buf); System.out.println(Kernel32Util.formatMessage(ret)); if (ret != 0) { assertEquals(0x906, ret); // NERR_NetNameNotFound assertNull(buf.getValue()); } else { SHARE_INFO_2 shareInfo = new SHARE_INFO_2(buf.getValue()); shareInfo.read(); assertEquals(SHARE_NAME, shareInfo.shi2_netname); assertEquals(0, shareInfo.shi2_permissions); } } finally { Netapi32Ext.INSTANCE.NetApiBufferFree(buf.getValue()); } } @Test public void testNetShareDel() { System.out.println("-> testNetShareDel"); SHARE_INFO_2 buf = getShareInfo(); IntByReference intRef = new IntByReference(); Netapi32Ext.INSTANCE.NetShareAdd(null, 2, buf, intRef); // delete int ret = Netapi32Ext.INSTANCE.NetShareDel(null, new WString( SHARE_NAME), 0); System.out.println(Kernel32Util.formatMessage(ret)); assertEquals(0 , ret); // re-del ret = Netapi32Ext.INSTANCE.NetShareDel(null, new WString( SHARE_NAME), 0); System.out.println(Kernel32Util.formatMessage(ret)); assertEquals(0x00000906, ret); } private SHARE_INFO_2 getShareInfo(){ SHARE_INFO_2 buf = new SHARE_INFO_2(); buf.shi2_netname = new WString(SHARE_NAME); buf.shi2_type = 0; buf.shi2_remark = new WString(SHARE_NAME); buf.shi2_permissions = 0; buf.shi2_max_uses = 4; buf.shi2_current_uses = 0; buf.shi2_path = new WString(shareFolder.getAbsolutePath()); buf.shi2_passwd = null; // no passwd return buf; } /** * @see Error: * https://msdn.microsoft.com/en-us/library/cc247101.aspx?f=255&MSPPError * =-2147217396 * */ @Test public void testNetShareAdd() { System.out.println("-> testNetShareAdd"); SHARE_INFO_2 buf = getShareInfo(); // add IntByReference intRef = new IntByReference(); int ret = Netapi32Ext.INSTANCE.NetShareAdd(null, 2, buf, intRef); System.out.println(Kernel32Util.formatMessage(ret)); assertEquals(0, ret); assertEquals(0, intRef.getValue()); // re-add ret = Netapi32Ext.INSTANCE.NetShareAdd(null, 2, buf, intRef); System.out.println(Kernel32Util.formatMessage(ret)); assertEquals(0x846, ret); // get info PointerByReference pbuf = new PointerByReference(); try { ret = Netapi32Ext.INSTANCE.NetShareGetInfo(null, new WString( SHARE_NAME), 2, pbuf); SHARE_INFO_2 shareInfo = new SHARE_INFO_2(pbuf.getValue()); shareInfo.read(); System.out.println(Kernel32Util.formatMessage(ret)); assertEquals(buf.shi2_netname, shareInfo.shi2_netname); assertEquals(buf.shi2_type, shareInfo.shi2_type); assertEquals(buf.shi2_remark, shareInfo.shi2_remark); assertEquals(buf.shi2_permissions, shareInfo.shi2_permissions); assertEquals(buf.shi2_max_uses, shareInfo.shi2_max_uses); assertEquals(buf.shi2_current_uses, shareInfo.shi2_current_uses); assertEquals(buf.shi2_path, shareInfo.shi2_path); assertNull(shareInfo.shi2_passwd); } finally { Netapi32Ext.INSTANCE.NetApiBufferFree(pbuf.getValue()); } } }
留言
張貼留言