mirror of
https://github.com/reactos/reactos.git
synced 2025-06-08 02:40:32 +00:00
232 lines
6 KiB
C
232 lines
6 KiB
C
![]() |
/*
|
||
|
* Adapted from code at http://support.fccps.cz/download/adv/frr/win32_ddk_mingw/win32_ddk_mingw.html - thanks!
|
||
|
*
|
||
|
File created by Frank Rysanek <rysanek@fccps.cz>
|
||
|
Source code taken almost verbatim from "Driver Development, Part 1"
|
||
|
published by Toby Opferman at CodeProject.com
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <windows.h>
|
||
|
/*#include <string.h>*/
|
||
|
#include <unistd.h> /* getcwd() */
|
||
|
|
||
|
#define MY_DRIVER_NAME "btrfs"
|
||
|
#define MY_DEVICE_NAME "\\Btrfs"
|
||
|
#define MY_DOSDEVICE_NAME "\\DosDevices\\" MY_DRIVER_NAME /* AKA symlink name */
|
||
|
/* for the loader and app */
|
||
|
#define MY_SERVICE_NAME_LONG "Driver Test2"
|
||
|
#define MY_SERVICE_NAME_SHORT MY_DRIVER_NAME
|
||
|
#define MY_DRIVER_FILENAME MY_DRIVER_NAME ".sys"
|
||
|
|
||
|
#define MAX_CWD_LEN 1024
|
||
|
static char cwd[MAX_CWD_LEN+3]; /* the XXXXX.sys filename will get appended to this as well */
|
||
|
|
||
|
/* geterrstr() taken verbatim from some code snippet at www.mingw.org by Dan Osborne. */
|
||
|
/* Apparently, it's a way to get a classic null-terminated string containing "last error". */
|
||
|
static char errbuffer[256];
|
||
|
|
||
|
static const char *geterrstr(DWORD errcode)
|
||
|
{
|
||
|
size_t skip = 0;
|
||
|
DWORD chars;
|
||
|
|
||
|
chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||
|
NULL, errcode, 0, errbuffer, sizeof(errbuffer)-1, 0);
|
||
|
errbuffer[sizeof(errbuffer)-1] = 0;
|
||
|
|
||
|
if (chars)
|
||
|
{
|
||
|
while (errbuffer[chars-1] == '\r' || errbuffer[chars-1] == '\n')
|
||
|
{
|
||
|
errbuffer[--chars] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chars && errbuffer[chars-1] == '.') errbuffer[--chars] = 0;
|
||
|
|
||
|
if (chars >= 2 && errbuffer[0] == '%'
|
||
|
&& errbuffer[1] >= '0' && errbuffer[1] <= '9')
|
||
|
{
|
||
|
skip = 2;
|
||
|
|
||
|
while (chars > skip && errbuffer[skip] == ' ') ++skip;
|
||
|
|
||
|
if (chars >= skip+2 && errbuffer[skip] == 'i' && errbuffer[skip+1] == 's')
|
||
|
{
|
||
|
skip += 2;
|
||
|
while (chars > skip && errbuffer[skip] == ' ') ++skip;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chars > skip && errbuffer[skip] >= 'A' && errbuffer[skip] <= 'Z')
|
||
|
{
|
||
|
errbuffer[skip] += 'a' - 'A';
|
||
|
}
|
||
|
|
||
|
return errbuffer+skip;
|
||
|
}
|
||
|
|
||
|
void process_error(void)
|
||
|
{
|
||
|
DWORD err = GetLastError();
|
||
|
printf("Error: %lu = \"%s\"\n", (unsigned long)err, geterrstr(err));
|
||
|
}
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
HANDLE hSCManager;
|
||
|
HANDLE hService;
|
||
|
SERVICE_STATUS ss;
|
||
|
int retval = 0;
|
||
|
BOOL amd64;
|
||
|
|
||
|
/* First of all, maybe concatenate the current working directory
|
||
|
with the desired driver file name - before we start messing with
|
||
|
the service manager etc. */
|
||
|
if (getcwd(cwd, MAX_CWD_LEN) == NULL) /* error */
|
||
|
{
|
||
|
printf("Failed to learn the current working directory!\n");
|
||
|
retval = -8;
|
||
|
goto err_out1;
|
||
|
} /* else got CWD just fine */
|
||
|
|
||
|
if (strlen(cwd) + strlen(MY_DRIVER_FILENAME) + 1 > MAX_CWD_LEN)
|
||
|
{
|
||
|
printf("Current working dir + driver filename > longer than %d ?!?\n", MAX_CWD_LEN);
|
||
|
retval = -9;
|
||
|
goto err_out1;
|
||
|
} /* else our buffer is long enough :-) */
|
||
|
|
||
|
strcat(cwd, "\\");
|
||
|
|
||
|
IsWow64Process(GetCurrentProcess(),&amd64);
|
||
|
strcat(cwd, amd64 ? "x64" : "x86");
|
||
|
|
||
|
strcat(cwd, "\\");
|
||
|
strcat(cwd, MY_DRIVER_FILENAME);
|
||
|
printf("Driver path+name: %s\n", cwd);
|
||
|
|
||
|
|
||
|
printf("Going to open the service manager... ");
|
||
|
|
||
|
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
|
||
|
if (! hSCManager)
|
||
|
{
|
||
|
printf("Uh oh:\n");
|
||
|
process_error();
|
||
|
retval = -1;
|
||
|
goto err_out1;
|
||
|
}
|
||
|
|
||
|
printf("okay.\n");
|
||
|
printf("Going to create the service... ");
|
||
|
|
||
|
hService = CreateService(hSCManager, MY_SERVICE_NAME_SHORT,
|
||
|
MY_SERVICE_NAME_LONG,
|
||
|
SERVICE_START | DELETE | SERVICE_STOP,
|
||
|
SERVICE_KERNEL_DRIVER,
|
||
|
SERVICE_DEMAND_START,
|
||
|
SERVICE_ERROR_IGNORE,
|
||
|
cwd,
|
||
|
NULL, NULL, NULL, NULL, NULL);
|
||
|
|
||
|
if(!hService)
|
||
|
{
|
||
|
process_error();
|
||
|
printf("\n already exists? Trying to open it... ");
|
||
|
hService = OpenService(hSCManager, MY_SERVICE_NAME_SHORT,
|
||
|
SERVICE_START | DELETE | SERVICE_STOP);
|
||
|
}
|
||
|
|
||
|
if(!hService)
|
||
|
{
|
||
|
printf("FAILED!\n");
|
||
|
process_error();
|
||
|
retval = -2;
|
||
|
goto err_out2;
|
||
|
}
|
||
|
|
||
|
printf("okay.\n");
|
||
|
printf("Going to start the service... ");
|
||
|
|
||
|
if (StartService(hService, 0, NULL) == 0) /* error */
|
||
|
{
|
||
|
printf("Uh oh:\n");
|
||
|
process_error();
|
||
|
retval = -3;
|
||
|
goto err_out3;
|
||
|
}
|
||
|
|
||
|
printf("okay.\n");
|
||
|
|
||
|
// TCHAR VolumeName[] = _T("Z:");
|
||
|
// TCHAR DeviceName[] = _T("\\Device\\VDisk1");
|
||
|
|
||
|
// printf("Mounting volume... ");
|
||
|
// if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH, "T:", "\\Device\\HarddiskVolume3"))
|
||
|
// {
|
||
|
// printf("Uh oh:\n");
|
||
|
// process_error();
|
||
|
// } else {
|
||
|
// printf("okay.\n");
|
||
|
// }
|
||
|
|
||
|
// if (!SetVolumeMountPointA("T:\\", "\\\\?\\Volume{9bd714c3-4379-11e5-b26c-806e6f6e6963}\\")) {
|
||
|
// printf("Uh oh:\n");
|
||
|
// process_error();
|
||
|
// } else {
|
||
|
// printf("okay.\n");
|
||
|
// }
|
||
|
|
||
|
printf("\n >>> Press Enter to unload the driver! <<<\n");
|
||
|
getchar();
|
||
|
|
||
|
// printf("Unmounting volume... ");
|
||
|
// if (!DefineDosDeviceA(DDD_REMOVE_DEFINITION, "T:", NULL))
|
||
|
// {
|
||
|
// printf("Uh oh:\n");
|
||
|
// process_error();
|
||
|
// } else {
|
||
|
// printf("okay.\n");
|
||
|
// }
|
||
|
|
||
|
printf("Going to stop the service... ");
|
||
|
if (ControlService(hService, SERVICE_CONTROL_STOP, &ss) == 0) /* error */
|
||
|
{
|
||
|
printf("Uh oh:\n");
|
||
|
process_error();
|
||
|
retval = -4;
|
||
|
}
|
||
|
else printf("okay.\n");
|
||
|
|
||
|
err_out3:
|
||
|
|
||
|
printf("Going to close the service handle... ");
|
||
|
if (CloseServiceHandle(hService) == 0) /* error */
|
||
|
{
|
||
|
printf("Uh oh:\n");
|
||
|
process_error();
|
||
|
retval = -6;
|
||
|
}
|
||
|
else printf("okay.\n");
|
||
|
|
||
|
err_out2:
|
||
|
|
||
|
printf("Going to close the service manager... ");
|
||
|
if (CloseServiceHandle(hSCManager) == 0) /* error */
|
||
|
{
|
||
|
printf("Uh oh:\n");
|
||
|
process_error();
|
||
|
retval = -7;
|
||
|
}
|
||
|
else printf("okay.\n");
|
||
|
|
||
|
err_out1:
|
||
|
|
||
|
printf("Finished! :-b\n");
|
||
|
|
||
|
return(retval);
|
||
|
}
|
||
|
|