Cannot get user name for a pid using rust winapi - winapi

I'm trying to get the user that is associated with a PID on windows.
I'm looking at the source for NTop https://github.com/gsass1/NTop as an example.
I can build and debug NTop source on Clion and the following code works correctly.
HANDLE ProcessTokenHandle;
if(OpenProcessToken(Process.Handle, TOKEN_READ, &ProcessTokenHandle)) {
DWORD ReturnLength;
GetTokenInformation(ProcessTokenHandle, TokenUser, 0, 0, &ReturnLength);
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
PTOKEN_USER TokenUserStruct = xmalloc(ReturnLength);
if(GetTokenInformation(ProcessTokenHandle, TokenUser, TokenUserStruct, ReturnLength, &ReturnLength)) {
SID_NAME_USE NameUse;
DWORD NameLength = UNLEN;
TCHAR DomainName[MAX_PATH];
DWORD DomainLength = MAX_PATH;
LookupAccountSid(0, TokenUserStruct->User.Sid, Process.UserName, &NameLength, DomainName, &DomainLength, &NameUse);
// FIXME: we cut user name here for display purposes because something like %9.9s does not work with MS's vsprintf function?
Process.UserName[9] = 0;
}
free(TokenUserStruct);
}
CloseHandle(ProcessTokenHandle);
}
When trying the same thing using rust winapi I get ERROR_NOACCESS every time no matter what I do.
Here's some example code that returns 0 as response code from OpenProcessToken and GetLastError will be ERROR_NOACCESS. It doesn't matter whether or not I run the program as administrator or not.
let pid: u32 = 8664; // process that is owned by me but can be any process, it will never work
let process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid);
let mut process_token_handle: PHANDLE = null_mut();
let s = OpenProcessToken(process_handle, TOKEN_READ, process_token_handle);
let last_error = GetLastError();
Anyone have any idea why this code would work in NTop using the C api and not work using rust winapi?

Related

Address field of SYMBOL_INFO is always 0?

I'm trying to use SymGetLineFromAddr64 to get the source file name of symbols loaded from a PDB. I load the PDB module and enumerate on the types/symbols, but the Address field from the SYMBOL_INFO pointer I get in the enumeration callback is always 0 so I can't use it to get the source file information. (SymGetLineFromAddr64 fails with error code 126
"The specified module could not be found.")
I also tried using the TI_GET_ADDRESS property from the SymInfo->Index but it's 0 too.
Here's my main:
int main(char **Argv, int Argc)
{
HANDLE Process = GetCurrentProcess();
DWORD ProcessId = GetProcessId(Process);
DWORD Options = SymGetOptions();
Options |= SYMOPT_DEBUG;
Options |= SYMOPT_LOAD_LINES;
Options |= SYMOPT_LOAD_ANYTHING; // Wanted to test if this would do anything at all, didn't do much
SymSetOptions(Options);
if (SymInitialize(Process, 0, 0) == TRUE)
{
char *FilePath = "C:\\Users\\pc\\Documents\\Saedo\\VSProjects\\x64\\Debug\\PDBReflector.pdb";
DWORD64 BaseAddress = 0x10000000;
DWORD FileSize = GetFileSize(FilePath);
DWORD64 Module = SymLoadModuleEx(Process, 0, FilePath, 0, BaseAddress, FileSize, 0, 0);
if (Module)
{
Reflector.Process = Process; //Reflector is just a global struct that contains the process and module base for use later
Reflector.ModuleBase = Module;
SymEnumTypes(Process, Module, EnumTypesProc, 0);
}
}
SymCleanup(Process);
return(0);
}
And here's the enumerator:
BOOL CALLBACK EnumTypesProc(SYMBOL_INFO *SymInfo, ULONG SymbolSize, VOID *UserContext)
{
if (SymInfo)
{
ULONG64 Address = SymInfo->Address; // Address is 0
//SymGetTypeInfo(Reflector.Process, Reflector.ModuleBase, SymInfo->Index, TI_GET_ADDRESS, &Address); // Address is 0 as well
IMAGEHLP_LINE64 LineInfo = {};
LineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD LineDisplacement = 0;
if (SymGetLineFromAddr64(Reflector.Process, Address, &LineDisplacement, &LineInfo))
{
Log("FILE: %s\n", LineInfo.FileName);
}
}
return(TRUE);
}
Compiling using VS2015 Community Edition, X64 Debug mode with /Zi for the Debug Information Format and "Optimize for debugging" (/DEBUG).
Note that I'm loading the PDB for the same executable that's running. I didn't think that would be the issue because I could load other type information just fine. And I also tried inspecting another PDB, the addresses were 0 as well.
Question: Why am I getting 0 in the Address field and how to actually get the right address so that I could retrieve the source file of a particular type/tag?
Pretty sure I'm missing something obvious here.
Thanks for any help.

shell32.dll: access violation during GetOpenFileName new thread

GetOpenFileName fails with access violation. File must be on DESKTOP and have long name.
Problem occurs only after first successful open of the file. Problem occurs when mouse cursor hovers over file as tool tip about to be displayed.
See the answer below. I'm leaving the original problem description below.
Mike D.
=======================
I'm using GetOpenFileName. I sometimes get a access violation deep inside shell32. The violation never occurs the first time this code is used, it often takes five or six tries. Also it appears that if one selects a file in second or two after the open file window pops up, the violation does not occur. Also, the call stack displayed when I debug this does not include any of my code. It's as if some independent thread is waking up to do something.
Any insights into how I might debug this greatly appreciated!
I made a "hello" world app exhibiting the same behavior. It, however, requires many more tries before it fails. It also seems that one has to switch directories before it will fail.
The GOFN is done from a thread created just for that purpose. Below is the code from the "hello world" app.
typedef struct
{
public:
HWND hWnd;
HINSTANCE hInst;
} def_params, *p_params;
DWORD WINAPI ReadLogFile_DataRecorderThread (PVOID pvoid);
void ReadLogFile_DataRecorder (HWND hWnd, HINSTANCE hInst) // ***************************
{
static def_params Params;
Params.hWnd = hWnd;
Params.hInst = hInst;
HANDLE T = CreateThread (NULL,0,ReadLogFile_DataRecorderThread,&Params,0,NULL);
CloseHandle (T);
return;
}
DWORD WINAPI ReadLogFile_DataRecorderThread (PVOID pvoid)
{
p_params P = (p_params) pvoid;
HWND hWnd = P->hWnd;
HINSTANCE hInst = P->hInst;
char ReadLogFileLastDir[256];
// static def_OpenFileHook Hook;
OPENFILENAME ofn;
char fn[MAX_PATH]="\0";
char filter[32]="Text Files\0*.TXT;\0\0";
char title[]="Open IMC Data Recorder Log File";
char defext[]="TXT";
int status;
// Get File Name
fn[0] = '\0';
ReadLogFileLastDir[0] = '\0';
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.hInstance = hInst;
ofn.hInstance = (HINSTANCE) GetWindowLong (hWnd, GWL_HINSTANCE);
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 0;
ofn.lpstrCustomFilter = NULL ;
ofn.nMaxCustFilter = 0 ;
ofn.lpstrFile = fn;
ofn.nMaxFile = sizeof(fn);
ofn.lpstrFileTitle = NULL;
if (ReadLogFileLastDir[0] == '\0')
{
SHGetSpecialFolderPath (NULL,ReadLogFileLastDir,0x0005,false);
};
ofn.lpstrInitialDir = ReadLogFileLastDir;
ofn.lpstrTitle = title;
ofn.Flags = OFN_FILEMUSTEXIST |
OFN_PATHMUSTEXIST |
OFN_EXPLORER |
// OFN_ENABLETEMPLATE |
OFN_ENABLESIZING |
// OFN_ENABLEHOOK |
OFN_READONLY;
ofn.lpstrDefExt = NULL;
ofn.lpfnHook = NULL; // Hook.DialogHook; // hook routine
ofn.lCustData = NULL; // (long) &Hook; // data for hook routine
ofn.lpTemplateName = NULL; // MAKEINTRESOURCE(IDD_HOOKFILEOPEN);
ofn.nFileOffset = 0 ;
ofn.nFileExtension = 0 ;
ofn.lpstrDefExt = defext;
status = GetOpenFileName (&ofn);
int S;
S = CommDlgExtendedError();
return 0;
}
When it fails, the call stack looks like this...
SHELL32! 7ca4e035()
SHELL32! 7cb2dc16()
SHELL32! 7cb2dd5a()
SHELL32! 7cb27361()
SHELL32! 7c9f40a3()
BROWSEUI! 75f81b9a()
SHLWAPI! 77f69548()
NTDLL! 7c927545()
NTDLL! 7c927583()
NTDLL! 7c927645()
NTDLL! 7c92761c()
KERNEL32! 7c80b50b()
Sorry but I am unable to get symbols for these as I have an old Visual C++ :-(
It appears to me that the problem occurs when the GOFN stuff is about to open the popup describing the file as the mouse cursor hovers over the file name.
The set of circumstances causing the problem are somewhat weird. Experiments show one has to do the following in the GOFN window:
Open a file on the DESKTOP
Hover over a long file name
If I do this twice, it always fails. The file name I used was
IMCLOG_20120323_1658_-_20120324_0653_CST_+DST_E2_2_second.TXT
I tried the same thing with NOTEPAD and the same problem occurs!
I found numerous reports of the same problem. For example:
Social.MSDN Problem report
CodeProject question
CodeGuru thread
There was also a Google cached link to a since-deleted MS Connect bug report. As you discovered, the problem seems to be particular to files in the Desktop.
The only suggested solution I found is to call CoInitializeEx(NULL) at the start of the thread, and call CoUninitialize() at the end, so that's worth trying.
Also, the MSDN documentation for GetOpenFileName() says:
Starting with Windows Vista, the Open and Save As common dialog boxes have been superseded by the Common Item Dialog.
So it may be worth discarding GetOpenFileName() completely.

Check if thread is alive in Windows

I recently tried to write a code to check if a thread in Windows is alive or not. I searched this forum and found discussions like: How to check if a process or thread is alive or not given their IDs in C++?.
I understand I can use OpenThread API. However it doesn't seem to work in my code as follows.
DWORD WINAPI myThread( LPVOID lpParam )
{
cout<<"child thread"<<endl;
return 0;
}
int main(void)
{
DWORD lTldID = 0;
HANDLE lTldHD = CreateThread(NULL, 0, myThread, 0, 0, &lTldID);
WaitForSingleObject(lTldHD, INFINITE);
HANDLE lHD = OpenThread(0x0040, FALSE, lTldID);
return 1;
}
I expect that the HANDLE lHD should be NULL since the thread 'myThread' should have finished at the time of calling OpenThread(). However, I always got NOT NULL values like 0x00000068. I don't know why this happened. Any idea?
Thanks,
Xiaomo
BOOL WINAPI GetExitCodeThread(
_In_ HANDLE hThread,
_Out_ LPDWORD lpExitCode
);
This function returns immediately. If the specified thread has not terminated and the function succeeds, the status returned is STILL_ACTIVE.

WriteProcessMemory in debugged process

I try to write simple debugger. For simplicity, assume the debugger runs under Windows XP.
At first I create new process as follows:
CreateProcess(processName,
NULL,
NULL,
NULL,
false,
DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,
NULL,
NULL,
&startInfo,
&openedProcessInfo);
And when I try to read or write something in memory of debugging process there are some problems. For example:
DWORD oldProtect;
if(!VirtualProtectEx(hProcess, breakpointAddr, 1, PAGE_EXECUTE_READWRITE, &oldProtect)) {
printf("Error: %d\n", GetLastError());
}
SIZE_T bytesRead = 0;
SIZE_T bytesWritten = 0;
BYTE instruction;
BOOL isOk = ReadProcessMemory(hProcess, breakpointAddr, &instruction, 1, &bytesRead);
BYTE originalByte = instruction;
instruction = 0xCC;
if(isOk && bytesRead == 1) {
isOk = WriteProcessMemory(hProcess, breakpointAddr, &instruction, 1, &bytesWritten);
if(isOk) {
isOk = FlushInstructionCache(hProcess, breakpointAddr, 1);
}
}
if(!isOk) {
printf("Error: %d\n", GetLastError());
}
It works, but not everywhere. It works when the address to which I want to write(read) something, is located within executable module (.exe).
But when I try to write(read) something within DLL library (for example, read at address of function VirtualAlloc) VirtualProtectEx returns false and GetLastError = 487 (Attempt to access invalid address) and ReadProcessMemory also returns false and GetLastError = 299 (Only part of a ReadProcessMemory or WriteProcessMemory request was completed.)
Debug privileges are enabled but it has no effect.
Your code looks fine, if you're running as administrator than the most likely cause of the problem is that breakpointAddr is an invalid address. VirtualProtectEx giving you the "Attempt to access invalid address" error supports this conclusion.

how can I find out which user send the print command to windows/windows server programmatically?

I have a windows network (peer-2-peer) as well as Active Directory and I need to log the name of users who send any kind of print to the server.
I want to write a program to log their username and/or their respective IP and I'm familiar with c#.net and c++ but I haven't found any clue regarding how to solve my problem.
is there any sorts of way to catch their name by the help of WMI or should dirty my hand with APIs(but which API I don't have any idea)?
regards.
Those features are exposed under the Spooler API.
EnumJobs will enumerate all the current jobs for a given printer. It will return a JOB_INFO_1 struct, which includes the username associated with a given print job:
typedef struct _JOB_INFO_1 {
DWORD JobId;
LPTSTR pPrinterName;
LPTSTR pMachineName;
LPTSTR pUserName;
LPTSTR pDocument;
LPTSTR pDatatype;
LPTSTR pStatus;
DWORD Status;
DWORD Priority;
DWORD Position;
DWORD TotalPages;
DWORD PagesPrinted;
SYSTEMTIME Submitted;
}JOB_INFO_1, *PJOB_INFO_1;
If you'd prefer WMI, you can use wmic.exe with the /node switch (or your preferred variation) and the Win32_PrintJob class. Roughly:
c:\> wmic /node 10.0.0.1
wmic> SELECT * FROM Win32_PrintJob
...will return a struct with all the print job information for the selected server. You can filter as you wish with the WHERE clause.
I would go with using WMI. That gives you the ability to query printer batches of printers associated with your system as well as pull all supporting properties. It's as simple as...
System.Management.ObjectQuery oq = new System.Management.ObjectQuery("SELECT * FROM Win32_PrintJob");
...creating an WMI object searcher and enumerating through the results.
Here's an example:
WMI query printers
I've used this in the past and if it doesn't have all of what you need, it should at least take care of monitoring the print queues.
http://www.merrioncomputing.com
http://www.merrioncomputing.com/Download/PrintQueueWatch/PrinterQueueWatchLicensing.htm
Source code link (from the OP's comment):
http://www.codeproject.com/KB/printing/printwatchvbnet.aspx
Find out which user has sent print job using C++ in Windows.
#include <WinSpool.h>
wstring GetUserNameFromPrintJob(wstring m_strFriendlyName)
{
wstring strDocName = L"";
wstring strMachineName = L"";
wstring strUserName = L"";
HANDLE hPrinter ;
if ( OpenPrinter(const_cast<LPWSTR>(m_strFriendlyName.c_str()), &hPrinter, NULL) == 0 )
{
/*OpenPrinter call failed*/
}
DWORD dwBufsize = 0;
PRINTER_INFO_2* pinfo = 0;
GetPrinter(hPrinter, 2,(LPBYTE)pinfo, dwBufsize, &dwBufsize); //Get dwBufsize
PRINTER_INFO_2* pinfo2 = (PRINTER_INFO_2*)malloc(dwBufsize); //Allocate with dwBufsize
GetPrinter(hPrinter, 2,(LPBYTE)pinfo2, dwBufsize, &dwBufsize);
DWORD numJobs = pinfo2->cJobs;
free(pinfo2);
JOB_INFO_1 *pJobInfo = 0;
DWORD bytesNeeded = 0, jobsReturned = 0;
//Get info about jobs in queue.
EnumJobs(hPrinter, 0, numJobs, 1, (LPBYTE)pJobInfo, 0,&bytesNeeded,&jobsReturned);
pJobInfo = (JOB_INFO_1*) malloc(bytesNeeded);
EnumJobs(hPrinter, 0, numJobs, 1, (LPBYTE)pJobInfo, bytesNeeded, &bytesNeeded, &jobsReturned);
JOB_INFO_1 *pJobInfoInitial = pJobInfo;
for(unsigned short count = 0; count < jobsReturned; count++)
{
if (pJobInfo != NULL)
{
strUserName = pJobInfo->pUserName //username
strMachineName = pJobInfo->pMachineName; //machine name
strDocName = pJobInfo->pDocument; // Document name
DWORD dw = pJobInfo->Status;
}
pJobInfo++;
}
free(pJobInfoInitial);
ClosePrinter( hPrinter );
return strUserName ;
}

Resources