Skip to content

Commit

Permalink
Add CommandLineToArgvW to Shell32 and corresponding util (#1360)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbwiddis committed Aug 7, 2021
1 parent d367f02 commit 7027e33
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ Features
* [#1336](https://github.com/java-native-access/jna/pull/1336): Add `HKEY_CURRENT_USER_LOCAL_SETTINGS` to `c.s.j.p.win32.WinReg` - [@Dani-Hub](https://github.com/Dani-Hub).
* [#1337](https://github.com/java-native-access/jna/pull/1337): Add `REG_NOTIFY_THREAD_AGNOSTIC` to `c.s.j.p.win32.WinNet` and update `REG_LEGAL_CHANGE_FILTER` - [@Dani-Hub](https://github.com/Dani-Hub).
* [#1338](https://github.com/java-native-access/jna/pull/1338): Add `RegNotifyChangeKeyValue` to `c.s.j.p.win32.Advapi32` - [@Dani-Hub](https://github.com/Dani-Hub).
* [#1340](https://github.com/java-native-access/jna/issues/1340): Added `CM_Get_DevNode_Registry_Property` to `c.s.j.p.win32.Cfgmgr32` and corresponding util in `c.s.j.p.win32.Cfgmgr32Util` - [@dbwiddis](https://github.com/dbwiddis).
* [#1340](https://github.com/java-native-access/jna/issues/1340): Add `CM_Get_DevNode_Registry_Property` to `c.s.j.p.win32.Cfgmgr32` and corresponding util in `c.s.j.p.win32.Cfgmgr32Util` - [@dbwiddis](https://github.com/dbwiddis).
* [#1352](https://github.com/java-native-access/jna/pull/1352): Add `BringWindowToTop` to `c.s.j.p.win32.User32` - [@kahgoh](https://github.com/kahgoh).
* [#1354](https://github.com/java-native-access/jna/pull/1352): Add `GetParent` to `c.s.j.p.win32.User32` - [@kahgoh](https://github.com/kahgoh).
* [#1360](https://github.com/java-native-access/jna/issues/1360): Add `CommandLineToArgvW` to `c.s.j.p.win32.Shell32` and corresponding util in `c.s.j.p.win32.Shell32Util` - [@dbwiddis](https://github.com/dbwiddis).

Bug Fixes
---------
Expand Down
26 changes: 26 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Shell32.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@
package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Guid.GUID;
import com.sun.jna.platform.win32.WTypes.LPWSTR;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HICON;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.INT_PTR;
import com.sun.jna.platform.win32.WinDef.UINT_PTR;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
Expand Down Expand Up @@ -409,5 +412,28 @@ public interface Shell32 extends ShellAPI, StdCallLibrary {
*/
HRESULT SetCurrentProcessExplicitAppUserModelID(WString appID);

/**
* Parses a Unicode command line string and returns an array of pointers to the
* command line arguments, along with a count of such arguments, in a way that
* is similar to the standard C run-time {@code argv} and {@code argc} values.
*
* @param lpCmdLine
* A Unicode string that contains the full command line. If this
* parameter is an empty string the function returns the path to the
* current executable file.
* @param pNumArgs
* Pointer to an {@code int} that receives the number of array
* elements returned, similar to {@code argc}.
* @return A pointer to an array of {@link LPWSTR} values, similar to
* {@code argv}. If the function fails, the return value is
* {@code null}. To get extended error information, call
* {@link Kernel32#GetLastError}. <br>
* CommandLineToArgvW allocates a block of contiguous memory for
* pointers to the argument strings, and for the argument strings
* themselves; the calling application must free the memory used by the
* argument list when it is no longer needed. To free the memory, use a
* single call to the {@link Kernel32#LocalFree} function.
*/
Pointer CommandLineToArgvW(WString lpCmdLine, IntByReference pNumArgs);
}

27 changes: 27 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Shell32Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Guid.GUID;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;

/**
Expand Down Expand Up @@ -112,4 +115,28 @@ public static final String getSpecialFolderPath(final int csidl, final boolean c
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
return Native.toString(pszPath);
}

/**
* Parses a command line string and returns an array of Strings of the command
* line arguments.
*
* @param cmdLine
* A string that contains the full command line. If this parameter is
* an empty string the function returns the path to the current
* executable file.
* @return An array of strings, similar to {@code argv}.
*/
public static final String[] CommandLineToArgv(String cmdLine) {
WString cl = new WString(cmdLine);
IntByReference nargs = new IntByReference();
Pointer strArr = Shell32.INSTANCE.CommandLineToArgvW(cl, nargs);
if (strArr != null) {
try {
return strArr.getWideStringArray(0, nargs.getValue());
} finally {
Kernel32.INSTANCE.LocalFree(strArr);
}
}
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
*/
package com.sun.jna.platform.win32;

import static org.junit.Assert.assertArrayEquals;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Guid.GUID;
import com.sun.jna.platform.win32.ShellAPI.APPBARDATA;
Expand All @@ -36,11 +39,11 @@
import com.sun.jna.platform.win32.WinDef.UINT_PTR;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;

import junit.framework.TestCase;


/**
* @author dblock[at]dblock[dot]org
* @author markus[at]headcrashing[dot]eu
Expand Down Expand Up @@ -260,4 +263,16 @@ public void testCurrentProcessExplicitAppUserModelID() {
Ole32.INSTANCE.CoTaskMemFree(ppszAppID.getValue());
}

public void testCommandLineToArgvW() {
WString cl = new WString("\"foo bar\" baz");
String[] argv = { "foo bar", "baz" };
IntByReference nargs = new IntByReference();
Pointer strArr = Shell32.INSTANCE.CommandLineToArgvW(cl, nargs);
assertNotNull(strArr);
try {
assertArrayEquals(argv, strArr.getWideStringArray(0, nargs.getValue()));
} finally {
Kernel32.INSTANCE.LocalFree(strArr);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
*/
package com.sun.jna.platform.win32;

import static org.junit.Assert.assertArrayEquals;

import junit.framework.TestCase;

/**
Expand Down Expand Up @@ -85,4 +87,10 @@ public void testGetKnownFolderPath()
// assertNotNull(Shell32Util.getKnownFolderPath(KnownFolders.FOLDERID_UserProgramFiles));
// assertNotNull(Shell32Util.getKnownFolderPath(KnownFolders.FOLDERID_UserProgramFilesCommon));
}

public void testCommandLineToArgv() {
String cl = "\"foo bar\" baz";
String[] argv = { "foo bar", "baz" };
assertArrayEquals(argv, Shell32Util.CommandLineToArgv(cl));
}
}

0 comments on commit 7027e33

Please sign in to comment.