Can someone help me with the syntax for calling a DLL? I want to get the user's username using the Windows API GetUserName function. I don't want to look up the username environment variable because that can be spoofed.
Advapi32.dll
BOOL WINAPI GetUserName(
_Out_ LPTSTR lpBuffer,
_Inout_ LPDWORD lpnSize
);
Thanks!
Here is some JSL that I wrote for getting the username from the system. This worked in JMP 10, running on Windows 7.
dll = Load DLL( "mpr.dll" );
dll << DeclareFunction(
"WNetGetUserA",
Convention( STDCALL ),
Alias ( "GetUserName" ),
Arg( UInt8, "format", input ),
Arg( AnsiString, "username", output ),
Arg( UInt64, "length", update ),
Returns( UInt32 )
);
username = " ";
unlen = length(username);
result = dll << GetUserName(0, username, unlen);
show(username);
dll << UnloadDLL();
First, you need to load the system DLL. I didn't have any luck with Advapi32.dll. But I found what I needed with mpr.dll. Notice I didn't need to specify a path to the DLL since it was on my system path.
dll = Load DLL("mpr.dll");
Next, you need to declare any method that you are going to call in the DLL. The method I want to use is actually called WNetGetUserA(), but by defining an alias, I can simply call it using GetUserName().
dll << DeclareFunction(
"WNetGetUserA",
Convention( STDCALL ),
Alias ( "GetUserName" ),
Arg( UInt8, "format", input ),
Arg( AnsiString, "username", output ),
Arg( UInt64, "length", update ),
Returns( UInt32 )
);
Now I want to define the variables that I am going to pass in as arguments. I create a username and initialize it to blanks. Then I use the length() function in JMP to get the current length of the buffer I just created.
username = " " ;
unlen = length(username);
Now I can call the function. Notice the first argument is input only, so I just use a constant instead of defining a variable. Then the show() command shows my username after making the call.
result = dll << GetUserName(0, username, unlen);
show(username);
Finally, I am done so I clean up.
dll << UnloadDLL();
I hope this works for you. If you come up with a better way, please let us know.
By the way, using loadDLL only works on Windows. It isn't supported on the Mac. For that reason I do a check at the top of my script.
Names Default To Here( 1 );
If( Host is( Mac ),
Print( "Sorry, this script is not supported on Mac." );
Stop();
);
Enjoy,
JohnP
JohnP,
Thanks so much! That's exactly what I'm looking for. Can't mark this as the correct answer because I didn't start this thread.
The original post also asked about the computer name. To get the computer name, use Kernel32.dll and the method name, GetComputerNameA(). So it will look like this:
dll = Load DLL( "Kernel32.dll" );
dll << DeclareFunction(
"GetComputerNameA",
Convention( STDCALL ),
Alias ( "GetComputerName" ),
Arg( AnsiString, "computername", output ),
Arg( UInt64, "length", update ),
Returns( UInt32 )
);
name = " ";
unlen = length(name);
result = dll << GetComputerName(name, unlen);
show(name);
dll << UnloadDLL();
JohnP
JMP 10 supports this query directly
Get Enviromental Variable("Computername")
Best,
-Matt
I need something that can't be hacked by something as simple as setting the environment variable. Thanks JohnP for both solutions!
thanks, syntax in JMP12 is actually:
Get Environment Variable("Computername");
For Mac OS
Try this:
If( Host is( "Mac" ),username=Get Environment Variable( "USER" );
stamp="Test "||username||", "||char(today());
);