How to use winapi functions in ring0 (kernel mode)? - c

I can't call FileTimeToSystemTime() method in driver. The error is:
error C4013: 'FileTimeToSystemTime' undefined; assuming extern returning int.
Also I can not include windows.h because I already included ntddk.h, and it will cause a lot of errors.
If I declare it as BOOL FileTimeToSystemTime(IN const PFILETIME, OUT PSYSTEMTIME); in the header I get next errors:
error C2061: syntax error : identifier 'FileTimeToSystemTime'
error C2059: syntax error : ';'
error C2059: syntax error : 'type'
error C4013: 'FileTimeToSystemTime' undefined; assuming extern returning int
And finally, If I write an implementation for this method:
BOOL FileTimeToSystemTime(const PFILETIME pFileTime, PSYSTEMTIME pSystemTime)
{
CALL_ENTRY
long long tmp;
memcpy(&tmp, pFileTime, sizeof (FILETIME));
time_t aTime_t = tmp / 10000;
tm aTm;
if (!gmtime_r(&aTime_t, &aTm ))
return FALSE;
pSystemTime->wYear = aTm.tm_year + 1900;
pSystemTime->wMonth = aTm.tm_mon;
pSystemTime->wDayOfWeek = aTm.tm_wday;
pSystemTime->wDay = aTm.tm_mday;
pSystemTime->wHour = aTm.tm_hour;
pSystemTime->wMinute = aTm.tm_min;
pSystemTime->wSecond = aTm.tm_sec;
pSystemTime->wMilliseconds = 0;
return TRUE;
}
I got the same errors as listed above. What is the right way to call this method in kernel mode ? Or how to call winapi functions from windows driver in general ?

The winapi is a sub-system on top of the native operating system. There were original three sub-systems for Windows NT: Posix, OS/2 and Win32. Designed to make porting programs from other operating system easy. Win32 was heavily influenced by the api for Windows 3.x. Posix and OS/2 were largely ignored and have been removed, Win32 won by a land-slide. These days called "Winapi" to avoid the "32", it was ported to 64-bit code with very modest changes.
In device driver land, you no longer work with such a sub-system, you program the native operating system. So you'll need to forget the winapi functions and use the native API instead.
You obtain the system time with KeQuerySystemTime(). Convert to local time if necessary ExSystemTimeToLocalTime(). You can generate the equivalent of SYSTEMTIME with the RtlTimeToTimeFields() helper function.

Related

Calling dll from a Win32 Console Application [C]

Hi everyone and thank you for your time. This was created in Visual Studio 2012,and I'm using the standard Windows Libraries.
I am attempting to call a DLL function explicitly and I believe the code I've written is correct; however, I am receiving an error. I'm not sure if it's an error in something that I've written in the small C console application or from the DLL which I do not have access to the internal workings of.
//global area
HINSTANCE _createInstance;
typedef UINT (CALLBACK* LPFNDLLFUNCLOOKUP)(AccuInput*, AccuOut*);
LPFNDLLFUNCLOOKUP lpfnDllFuncCASSLookup;
typedef UINT (CALLBACK* LPFNDLLFUNCINIT)(BSTR);
LPFNDLLFUNCINIT lpfnDllFuncInit;
typedef UINT (CALLBACK* LPFNDLLFUNCCLOSE)();
LPFNDLLFUNCCLOSE lpfnDllFuncClose;
HMODULE unmanagedLib;
Here is my main function:
int main() {
// Load Library
BSTR configFile;
unmanagedLib = LoadLibraryA((LPCSTR) "AccuAddressUnMgd.dll");
// Initialize AccuAddress COM dll
lpfnDllFuncInit = (LPFNDLLFUNCINIT)GetProcAddress(unmanagedLib, (LPCSTR)"Init");
// This function will lookup the address
lpfnDllFuncCASSLookup = (LPFNDLLFUNCLOOKUP)GetProcAddress(unmanagedLib, (LPCSTR)"AccuCassLookup");
// This function will call AccuAddress COM DLL Close function
lpfnDllFuncClose = (LPFNDLLFUNCCLOSE)GetProcAddress(unmanagedLib, (LPCSTR)"Close");
// Append “config.acu” file path.
configFile = SysAllocString(L"C:\PathTo\Config.acu");
printf("ConfigPath created");
lpfnDllFuncInit(configFile);
printf("ConfigFile consumed");
SysFreeString(configFile);
return 0;
}
This is the error that I receive:
Unhandled exception at at 0x75D4C54F in RDISample1.exe: Microsoft C++ exception: _com_error at memory location 0x001AFAC0.
The error occurs at:
lpfnDllFuncInit(configFile);
So, I guess my question is two parts. Based off the code can I say for a fact that the error is in the DLL function?
Second question, when calling GetProcAddress what would be the point (if any) for encapsulating the string in LPCSTR like a function versus typecasting?
ie
lpfnDllFuncClose = (LPFNDLLFUNCCLOSE)GetProcAddress(unmanagedLib, LPCSTR("Close"));
Thanks again for the help. I've been doing a fair amount of research yet DLLs still have been puzzled.
The initial error is caused by the library you're using failing to correctly handle a file that doesn't exist.
The path you gave contains single slashes \, which are treated as escape characters, not path separators. Path separators must be escaped, i.e. \\ to be treated correctly.
There is no point casting a string literal to LPCSTR.
As for the _com_error that is definitely coming from the DLL. I would suggest wrapping that in a:
try
{
...
} catch(_com_error const & e)
{
wprintf(L"Caught a com error: %s\r\n", e.ErrorMessage());
}
And then you might be able to figure out what is wrong.

When I was using a dll comiled by msvc_2015 in qt's program,my program works ok,but debuging shows segemts error

firstly, I have to say the dll was translated by MatLab's m file, which was compiled by c compiler using msvc_2015.
The dll was C shared library, which was said that has a common interface.
I don‘t think it's MatLab's error,because my program works.
The qt was compiled by MinGW_64_4.9.3 on my own computer,so i think qt's configuration is OK.
I can’t figure out why my program works OK, but debugging error, once I was using the fooInitialize(), there were a lot of segments error when debugging
QLibrary lib("foo.dll");
QMessageBox msg;
if(lib.load())
{
QMessageBox::information(NULL,"OK","DLL load is OK!");
Fun mlfFoo=(Fun)lib.resolve("mlfFoo"); //
Fun2 init=(Fun2)lib.resolve("fooInitialize");//
Fun2 termi=(Fun3)lib.resolve("fooTerminate");//
if (mlfFoo) //
{
QMessageBox::information(NULL,"OK","Link to Function is OK!");
init(); //
double numbrOut,*out;
double data[]={1};
mxArray* array_in,*array_out ;
array_in = mxCreateDoubleMatrix(1, 1, mxREAL);//
memcpy(mxGetPr(array_in),data , sizeof(double));
array_out=NULL;
mlfFoo(1, &array_out,array_in);
out=mxGetPr(array_out);
numbrOut=out[0];
mxDestroyArray(array_in); array_in=0;
mxDestroyArray(array_out); array_out = 0;
out=0;
if(numbrOut==10) QMessageBox::information(NULL,"NO","perfect!!!!");
termi();
}
else
QMessageBox::information(NULL,"NO","Linke to Function is not OK!!!!");
}
else
QMessageBox::information(NULL,"NO","DLL is not loaded!");`
I got this few minutes ago
"while parsing target library list: not well-formed (invalid token)"
"SuspendThread (tid=0x788) failed. (winerr 2)"
the dll's header file was made by matlab using msvc , I compared it to the samples in the matlab's document , it is the similar

How to determine Windows version in future-proof way

I noticed that GetVersionEx() is declared deprecated. Worse yet, for Windows 8.1 (and presumably future releases) the version number is limited by the application manifest.
My goal is to collect analytics on operating systems which the users are running, so I can appropriately target support. I would like a future-proof solution for collecting this data. Updating the manifest won't work because I can only update the manifest for Windows versions which have already been released, not for future versions. The suggested replacement API, the version helper functions, is useless.
How can I collect the actual Windows version number?
To clarify: By "future proofing", I just mean that I want something that has a reasonably good chance of working on the next version of Windows. Nothing is certain, but the docs do say that GetVersionEx() won't work.
MSDN has an example showing how to use the (useless for your scenario) version helper functions, but in the introduction is the following:
To obtain the full version number for the operating system, call the GetFileVersionInfo function on one of the system DLLs, such as Kernel32.dll, then call VerQueryValue to obtain the \StringFileInfo\\ProductVersion subblock of the file version information.
As of right now, neither the GetFileVersionInfo nor VerQueryValue function are deprecated.
Example
This will extract the product version from kernel32.dll and print it to the console:
#pragma comment(lib, "version.lib")
static const wchar_t kernel32[] = L"\\kernel32.dll";
wchar_t *path = NULL;
void *ver = NULL, *block;
UINT n;
BOOL r;
DWORD versz, blocksz;
VS_FIXEDFILEINFO *vinfo;
path = malloc(sizeof(*path) * MAX_PATH);
if (!path)
abort();
n = GetSystemDirectory(path, MAX_PATH);
if (n >= MAX_PATH || n == 0 ||
n > MAX_PATH - sizeof(kernel32) / sizeof(*kernel32))
abort();
memcpy(path + n, kernel32, sizeof(kernel32));
versz = GetFileVersionInfoSize(path, NULL);
if (versz == 0)
abort();
ver = malloc(versz);
if (!ver)
abort();
r = GetFileVersionInfo(path, 0, versz, ver);
if (!r)
abort();
r = VerQueryValue(ver, L"\\", &block, &blocksz);
if (!r || blocksz < sizeof(VS_FIXEDFILEINFO))
abort();
vinfo = (VS_FIXEDFILEINFO *) block;
printf(
"Windows version: %d.%d.%d",
(int) HIWORD(vinfo->dwProductVersionMS),
(int) LOWORD(vinfo->dwProductVersionMS),
(int) HIWORD(vinfo->dwProductVersionLS));
free(path);
free(ver);
Yikes, the currently accepted answer is over-complicated. Here's how to get the version of the current windows (with build numbers) quickly and reliably without requiring manifests and other nonsense tricks. And works on Windows 2000 and newer (i.e. every version of Windows in existence).
Short answer: use RtlGetVersion.
Don't have the Windows Driver Development Kit? Then it's a little less simple than including the header and using the function. Here's how you do it both with and without the WDK.
With WDK, include:
// Required for RtlGetVersion()
#pragma comment(lib, "ntdll.lib")
#include <Ntddk.h>
Without WDK, include:
// Required for RtlGetVersion()
#pragma comment(lib, "ntdll.lib")
// Define the function because we don't have the driver development
// kit headers. We could probably acquire them but it makes development
// onboarding a pain in the ass for new employees.
extern "C" {
typedef LONG NTSTATUS, *PNTSTATUS;
#define STATUS_SUCCESS (0x00000000)
// Windows 2000 and newer
NTSYSAPI NTSTATUS NTAPI RtlGetVersion(PRTL_OSVERSIONINFOEXW lpVersionInformation);
}
Now, simply get the accurate version details:
RTL_OSVERSIONINFOEXW osVers;
osVers.dwOSVersionInfoSize = sizeof(osVers);
// fill the structure with version details
NTSTATUS status = RtlGetVersion(&osVers);
// this should always succeed
assert(status == STATUS_SUCCESS);
The osVers variable now contains the accurate major, minor, and build number. No need to read file versions and no need to dynamically load libraries at runtime.
Please vote this above the other answer so this correct code can be used in applications rather than the rube-goldberg other answer. Thanks.

How to get number of the system calls after the kernel boot in xv6?

I want to write a simple "C" program to find number of system calls after OS boot. I am following other system calls like fork() or getpid() and basically copying most of their stuff. I am unsure where/when I should increase my counter? Any example?
Is it a good idea to define the counter in kernel/syscall.c and increment it accordingly?
void
syscall(void)
{
int num;
counter++; //mona
num = proc->tf->eax;
if(num > 0 && num < NELEM(syscalls) && syscalls[num] != NULL) {
proc->tf->eax = syscalls[num]();
} else {
cprintf("%d %s: unknown sys call %d\n",
proc->pid, proc->name, num);
proc->tf->eax = -1;
}
}
Also here's the code I've got so far in kernel/sysproc.c for my trivial system call:
sys_getsyscallinfo(void)
{
return counter; //mona
}
However I receive this error:
kernel/sysproc.c: In function ‘sys_getsyscallinfo’:
kernel/sysproc.c:48: error: ‘counter’ undeclared (first use in this function)
kernel/sysproc.c:48: error: (Each undeclared identifier is reported only once
kernel/sysproc.c:48: error: for each function it appears in.)
make: *** [kernel/sysproc.o] Error 1
I defined a counter variable as extern int in kernel/defs.h and made use of it in syscall definition as the return value in kernel/sysproc.c and increased it where all trap handlings is done in kernel/syscall.c. I hope it helps.
This would need editing entry.S file. Last time I was with the kernel, it was in .../arch/kernel/ directory. In that file, it first validates the system call, the call it using call instruction. You would have to do things after this validation and before system call in actually put.
You need not worry about how do I access variables in User Land, there is base pointer in that entry.S.
By the way this is 'new' way of calling system call(thanks to P II+ processors).. initially there used to be software interrupt int 0x80. So also check with which version of kernel you are working on.
I may be wrong here.. I am just explaining one way(which is probably worst and/or wrong) based on some knowledge. if You/someone_else implement this, please post success/failure with minimal code.
Once I get time out of Windows(chances are less) I am going to write this code myself.

What's wrong with the C code below?

The code below is from this answer:
#include <windows.h>
int main()
{
HANDLE h = ::CreateFile(L"\\\\.\\d:", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
STORAGE_DEVICE_NUMBER info = {};
DWORD bytesReturned = 0;
::DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &info, sizeof(info), &bytesReturned, NULL);
}
When I compile and run the above,get error like this:
error C2059: syntax error : ':'
error C2059: syntax error : '}'
error C2143: syntax error : missing ';' before ':'
UPDATE
AFter saving the above as a cpp file,I got this error:
error C2664: 'CreateFileA' : cannot convert parameter 1 from 'const wchar_t [7]' to 'LPCSTR'
Plain C doesn't have namespaces, so you need to leave out the :: global namespace specifiers. Those would only be valid in C++.
The L in front of the string specifies that this is a wide character string. If your project doesn't use wide characters, leave out the L to get a normal character string. If you need to support both variants you can also use the _T macro: _T("...") expands to the correct variant of string literal depending on your project settings.
I'm pretty sure that you can't use :: as part of an identifier name in the C programming language. This looks more like some bizarre, bastardized usage of C++. IIRC, :: by itself in front of an identifier specified that this was in the global or file scope (to avoid potentially clashing with, say, methods in a class).
It's not C, it's C++. Drop the double colons (or compile it as C++).
Also, the string constant uses wide characters. Drop the L in front of the open quote.
So, I guess your question is more about getting the result you want than the reason for the code not compiling :)
Now you've got it working, the DeviceIoControl() call will be filling in the STORAGE_DEVICE_NUMBER structure you're passing to it with the results you want. So, you should find that info.DeviceType now holds the device type, info.DeviceNumber holds the device number, and info.PartitionNumber the partition number.
Test for success before using the returned values. I'd maybe try it on the C: drive rather than the D: drive, as you're doing at the moment, until I was sure it was working; at least you know you've pretty much always got a C: drive in Windows :) So, use \\\\.\\c: rather than \\\\.\\d:.
Anyway, untested, but:
if (::DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &info, sizeof(info), &bytesReturned, NULL))
{
std::cout << "Device: " << info.DeviceNumber <<
" Partition: " << info.PartitionNumber << std::endl;
} else {
std::cerr << "Ooops. The DeviceIoControl call returned failure." << std::endl;
}
...obviously, you'd need a #include <iostream> for this to work, as I'm dumping the values using iostream, but you can print these out however you want, or message box them, bearing in mind you're already bringing in windows.h.
Bear in mind it's been a decade or so since I did any Windows C++ work, but maybe this'll get you going...

Resources