Hi i have the following code which i would like to convert to C#. Could you share some light here how can i convert those to C#? i am not well familiar with C++. Especially on the function DeviceIoControl which it is calling the WinBase API. In C#, what function should i use to replace DeviceIOCOntrol?
shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
accessMode = GENERIC_READ | GENERIC_WRITE;
sprintf(ff, "\\\\.\\%s", device);
hFile = CreateFile(ff, accessMode, shareMode, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
*response = -1;
sprintf((response + 1), "Failed to open device %s", device);
return;
}
status = DeviceIoControl(hFile,
IOCTL_SCSI_GET_ADDRESS,
NULL,
0,
inquiry_data,
sizeof(inquiry_data),
&returned,
FALSE);
You must use P/Invoke interop to access DeviceIoControl. Here is a link that has similar calls and should be a good starting point: Defrag API C# wrappers
This is retrieving the SCSI bus #, ID # on that bus, and LUN on that ID. You'll probably need to figure out what's being done with that to figure out how to translate/replace it meaningfully. If memory serves, you can retrieve some of the same information via WMI, but there's a pretty fair chance that won't do a lot of good -- the primary uses for this information is to pass it back when making other DeviceIoControl calls.
Related
I'm trying to write a Python script that reads a series of memory locations of a particular process.
How can I do this in Python?
I'll be using Windows if it matters. I have the processes PID that I'm attempting to read/edit.
Am I going to have to revert to calling ReadProcessMemory() and using ctypes?
I didn't see anything in the standard python libraries but I found an example using ctypes like you suggested on another site:
from ctypes import *
from ctypes.wintypes import *
OpenProcess = windll.kernel32.OpenProcess
ReadProcessMemory = windll.kernel32.ReadProcessMemory
CloseHandle = windll.kernel32.CloseHandle
PROCESS_ALL_ACCESS = 0x1F0FFF
pid = 4044 # I assume you have this from somewhere.
address = 0x1000000 # Likewise; for illustration I'll get the .exe header.
buffer = c_char_p("The data goes here")
bufferSize = len(buffer.value)
bytesRead = c_ulong(0)
processHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
if ReadProcessMemory(processHandle, address, buffer, bufferSize, byref(bytesRead)):
print "Success:", buffer
else:
print "Failed."
CloseHandle(processHandle)
Yes, ctypes (or win32all) and ReadProcessMemory are exactly the way to go. Were you looking for something extra/different? What, in particular?
See http://www.windowsreference.com/windows-xp/dos-commands-and-equivalent-linux-commands/
You can use tasklist.exe to list processes, then scrape the results. Then use taskkill.exe (or tstskill.exe) to end them.
But ctypes and kernal32 is probably safer.
I need to get hdd transfer mode(dma or pio) and print it, you can find it in device manager(in red circle in the screenshot).
So I need to get the info in red circle from programm. I've tried to use wmi classes, but Win32_DiskDrive, Win32_IDEController and others dont't provide the information I need. The closest to the property window from device manager was Win32_IDEController, field Win32_IDEController["Name"] returns string ATA Channel 1.
Also I've found this https://msdn.microsoft.com/en-us/library/windows/hardware/ff550142(v=vs.85).aspx , but it use irb.h, that is part of ddk(wdk) and I've never used it before, so I don't even know how to use this function.
Now I'm learning the WDK) Any solution in any language will good, in project I'm using C#, but if the solution will be in another language I can write "DMA" or "PIO" to a file in this solution, execute it .exe from C# and read from file. OFC solution in C# will be appreciated more.
You can use autoit (https://www.autoitscript.com) to read it direct from the GUI.
Sample (be carefull with different Windows versions and different languages):
Run ("mmc c:\windows\system32\devmgmt.msc")
WinWaitActive ( "Device Manager" )
send("{tab}{down}{down}{down}{down}{down}{down}{down}{NUMPADADD}{down}!{enter}")
WinWaitActive ( "Primary IDE Channel Properties" )
send("^{tab}")
$drivemode = ControlGetText("Primary IDE Channel Properties", "", "Static4")
ControlClick("Primary IDE Channel Properties","Cancel","Button6")
WinKill ( "Device Manager" )
If you want to use Autoit in C#:
https://www.autoitscript.com/forum/topic/177167-using-autoitx-from-c-net/
You can use the AdapterUsesPio member from the STORAGE_ADAPTER_DESCRIPTOR structure. Here is a C++ example that demonstrates how to query a disk for it:
#include "stdafx.h"
int main()
{
wchar_t path[1024];
wsprintf(path, L"\\\\?\\C:"); // or L"\\\\.\\PhysicalDrive0"
// note we use 0, not GENERIC_READ to avoid the need for admin rights
// 0 is ok if you only need to query for characteristics
HANDLE device = CreateFile(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (device == INVALID_HANDLE_VALUE)
return 0;
STORAGE_PROPERTY_QUERY query = {};
query.PropertyId = StorageAdapterProperty;
query.QueryType = PropertyStandardQuery;
STORAGE_ADAPTER_DESCRIPTOR descriptor = {};
DWORD read;
if (!DeviceIoControl(device, IOCTL_STORAGE_QUERY_PROPERTY,
&query,
sizeof(query),
&descriptor,
sizeof(descriptor),
&read,
NULL
))
{
wprintf(L"DeviceIoControl error: %i\n", GetLastError());
}
else
{
wprintf(L"AdapterUsesPio: %i\n", descriptor.AdapterUsesPio);
}
CloseHandle(device);
return 0;
}
The code provided by Jon in the following thread seems to illustrate exactly what I want to do
Running a process at the Windows 7 Welcome Screen
Unfortunately it's in C#, a language I don't know at all. I'm trying to translate the code to Pascal (a recent version of Lazarus on Windows 7). From reading between the lines, I think I may have got a lot of it - however, I'll only know if I've got it wrong when it fails to do its job. At the moment it is failing to compile at the following point.
if (!DuplicateTokenEx(userToken, 0x10000000, ref tokenAttributes,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation,
out newToken)) {
log("ERROR: DuplicateTokenEx returned false - "
My Pascal version:
If Not DuplicateTokenEx(UserToken, MAXIMUM_ALLOWED, tokenAttributes,
SecurityImpersonation, TokenPrimary, newToken) then
Writeln(DLog, 'Failed to duplicate security token');
Lazarus throws an error on the fifth of the six parameters.
dmain.pas(189,110) Error: Incompatible type for arg no. 5: Got "TOKEN_TYPE", expected "_TOKEN_TYPE" - which indicates I haven't understood what the parameters are doing. (Changing parameter 5 to TokenImpersonation throws the same error.)
Further down, I get even more lost:
tokPrivs.Privileges = new LUID_AND_ATTRIBUTES[1];
tokPrivs.Privileges[0].Luid = seDebugNameValue;
tokPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
I can see that the structure type LUID_AND_ATTRIBUTES is in the Windows API but it seems it's not recognised by Lazarus.
In short, I'm groping around in the dark. I've tried Googling for "C# for Pascal programmers" but didn't find anything helpful. Learning C# isn't a trivial undertaking, so I be would really grateful for any hints on the differences between it and Object Pascal, and how to translate this code.
Edit: Unfinished code as requested.
function RunOurProcess(ProgramName: String): Boolean;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
NewToken, Token, UserToken: THandle;
WPID: DWord;
ThreadAttributes, TokenAttributes: TSecurityAttributes;
TOKPrivs: TTokenPrivileges;
begin
FillChar(StartInfo, SizeOf(TStartupInfo), #0);
FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
StartInfo.cb:= SizeOf(TStartupInfo);
{ Insert handle of current desktop - without this, GUI app is not visible!
To appear before logon, lpDesktop value should be 'winsta0\WinLogon' }
StartInfo.lpDesktop:= PChar('winsta0\WinLogon');
// Save the process ID of the WinLogon process
WPID:= FindInProcesses('Winlogon.exe');
// Get the handle of this
Token:= OpenProcess(TOKEN_QUERY or TOKEN_IMPERSONATE or TOKEN_DUPLICATE, False, WPID);
// Open a process token using the handle above
If OpenProcessToken(Token, TOKEN_QUERY or TOKEN_IMPERSONATE or TOKEN_DUPLICATE, UserToken) then
Writeln(DLog, 'Opened process token for WinLogon')
else
Writeln(DLog, 'Failed to open process token for WinLogon');
// Create a new token
NewToken:= 0;
tokenAttributes.nLength:= SizeOf(tokenAttributes);
threadAttributes.nLength:= SizeOf(threadAttributes);
If Not DuplicateTokenEx(UserToken, MAXIMUM_ALLOWED, tokenAttributes, SecurityImpersonation, TokenImpersonation, newToken) then
Writeln(DLog, 'Failed to duplicate security token');
// Elevate the privileges of the token
AdjustTokenPrivileges(NewToken, False, {NewState, BufferLength, PreviousState, ReturnLength});
// LogOnUser
// If successful, CreateProcessAsUser
// In progress - code below needs to go before 'CreateProcessAsUser'
StartInfo.cb:= SizeOf(TStartupInfo);
// Insert handle of current desktop - without this, GUI app is not visible!
StartInfo.lpDesktop:= PChar('winsta0\WinLogon');
end; // RunOurProcess
I notice now that I get the following error if I try to find the declaration for "DuplicateTokenEx"
C:\lazarus\fpc\2.6.1\source\packages\winunits-jedi\src\jwawindows.pas(366,5) Error: include file not found "JwaLmErr.pp"
Here's how to solve the compilation problems.
The call to DuplicateTokenEx actually fails on the third parameter. Looking at the declaration, it is LPSECURITY_ATTRIBUTES which is ^TSecurityAttributes. Now, tokenAttributes is of type TSecurityAttributes so you need to pass its address:
If Not DuplicateTokenEx(..., #tokenAttributes, ...) then
And similarly in the call to AdjustTokenPrivileges. The C# code is:
AdjustTokenPrivileges(newToken, false, ref tokPrivs, 0, IntPtr.Zero, IntPtr.Zero)
Translated to Pascal that would be:
AdjustTokenPrivileges(NewToken, False, #TOKPrivs, 0, nil, nil)
I've no idea whether or not the code will solve your problem. I think that's beyond the remit of this question – at least that's my excuse and I'm sticking to it!
VBoxManage.exe is an Oracle VirtualBox companion utility, which allows to control VMs via command line. It can do numerous operations, including start/stop and screen capturing.
I am interested, which API it uses?
How can I capture VM screen or send keyboard or mouse commands there without this heavy commandline utility? Which language is better? Is is possible to access this API with Java?
One of the advantages to using an open source project is supposed to be that you can answer such questions by looking at the source.
VBoxManage is located in the source repository under /src/VBox/Frontends/VBoxManage. The code you're looking for is in VBoxManageControlVM.cpp under the condition if (!strcmp(a->argv[1], "screenshotpng")):
ComPtr<IDisplay> pDisplay;
CHECK_ERROR_BREAK(console, COMGETTER(Display)(pDisplay.asOutParam()));
ULONG width, height, bpp;
CHECK_ERROR_BREAK(pDisplay,
GetScreenResolution(displayIdx, &width, &height, &bpp));
com::SafeArray<BYTE> saScreenshot;
CHECK_ERROR_BREAK(pDisplay, TakeScreenShotPNGToArray(displayIdx,
width, height, ComSafeArrayAsOutParam(saScreenshot)));
RTFILE pngFile = NIL_RTFILE;
vrc = RTFileOpen(&pngFile, a->argv[2], RTFILE_O_OPEN_CREATE | RTFILE_O_WRITE |
RTFILE_O_TRUNCATE | RTFILE_O_DENY_ALL);
if (RT_FAILURE(vrc))
{
RTMsgError("Failed to create file '%s'. rc=%Rrc", a->argv[2], vrc);
rc = E_FAIL;
break;
}
vrc = RTFileWrite(pngFile, saScreenshot.raw(), saScreenshot.size(), NULL);
if (RT_FAILURE(vrc))
{
RTMsgError("Failed to write screenshot to file '%s'. rc=%Rrc",
a->argv[2], vrc);
rc = E_FAIL;
}
RTFileClose(pngFile);
So it's done via a COM API, and you can look at:
Is it possible to call a COM API from Java?
Googling for TakeScreenShotPNGToArray finds the display interface:
https://www.virtualbox.org/sdkref/interface_i_display.html
From there you can find the list of all the other things like mouse and keyboard:
https://www.virtualbox.org/sdkref/annotated.html
i am trying to get the text in SysListView32 from another app by C#.
i can get the LVM_GETITEMCOUNT well but LVM_GETITEMW = 0x1000 + 13 always returns -1. how can i get the text by C#? i am new. thanks very much!
ParenthWnd = FindWindow(ParentClass, ParentWindow);
if (!ParenthWnd.Equals(IntPtr.Zero))
{
zWnd = FindWindowEx(ParenthWnd, zWnd, zClass, zWindow);
if (!zWnd.Equals(IntPtr.Zero))
{
int user = SendMessage(zWnd, LVM_GETITEMCOUNT, 0, 0);
}
You need to work harder to read and write the LVITEM memory since you are working with a control owned by another process. You therefore need to read and write memory in that process. You can't do that without calling ReadProcessMemory, WriteProcessMemory etc.
The most commonly cited example of the techniques involved is this Code Project article: Stealing Program's Memory. Watch out for 32/64 bit gotchas.