I am having some trouble with the WriteFile function in C.
I open a handle to the volume T: with CreateFile:
HANDLE hvol = CreateFile("\\\\.\\T:", GENERIC_READ | GENERIC_WRITE, 3,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
Set the file pointer with SetFilePointer:
DWORD offset = SetFilePointer(hvol, bps + datarunOffset[0], NULL, FILE_BEGIN);
And write with:
bool wsuccess = WriteFile(hvol, filearray, secfilesize, &byteswritten, NULL);
Where filearray is an array of the byte values of a small file, and secfilesize is the number of elements in filearray rounded to a multiple of the disk's sector size (512).
If I have set the file pointer to 0x400 (the second sector of $Boot) then the array is written with no error codes.
If I have set the file pointer to 0x3200 (the second sector of $UpCase) then nothing is written and
error code 5: access denied
is returned.
I cannot find a solution and I have full control over the volume. It just seemed odd that I could write to $Boot but not $UpCase, is there any reason for this? and can anyone offer a solution?
Related
To get the disk serial number I would use function GetVolumeInformation but I couldn't find a way to change it using windows api like VolumeID program from Sysinternals does.
There is no Windows API to do this easily, you will have to manually overwrite the volume ID in the boot sector of the drive. This involves (at least) three different operations:
Get an handle to the volume.
Read the boot sector and parse it to recognize the filesystem type (FAT vs FAT32 vs NTFS, etc.).
Overwrite the Volume ID field and re-write the modified boot sector back to the disk.
It's not that simple of an operation, but this is how Sysinternals VolumeID does it. Note that boot sector fields and offsets are different for every filesystem.
The way SysInternals Volume ID does this. First open the volume with CreateFile API
char volumeName[8];
char const driveLetter = 'F';
char const volumeFormat[] = "\\\\.\\%c:";
sprintf_s(volumeName,8,volumeFormat, driveLetter);
HANDLE hVolume = CreateFileA(volumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
Next read 512 bytes (This is read into a struct, i'm not sure the exact structure)
DWORD dwBytesRead;
ReadFile(hVolume,&volumeHeader, 512, &dwBytesRead, NULL);
Using struct defined like this:
struct VOLUME_HEADER
{
char v1[3];
char v2[36];
int v3;
char v4[13];
int v5;
int v6;
char v7[430];
char v8[12];
};
The structure is checked if it is NTFS, FAT, FAT32 etc.
if (!strncmp(volumeHeader.v2, "NTFS", 4u))
{
printf("Volume is NTFS!\n");
}
else if (!strncmp(volumeHeader.v7, "FAT32", 5u))
{
printf("Volume is FAT32!\n");
}
else
{
if (strncmp(volumeHeader.v4, "FAT", 3u))
{
printf("\n\nUnrecognized drive type\n");
return 0;
}
printf(":Volume is FAT!\n");
}
Then a 32-bit integer is updated in this structure with the new volume ID. If you retrieve a specific volume like NTFS you can find the offset of the volume ID if you know the existing one. Then file pointer is set back to beginning of file and data is written back with WriteFile API.
SetFilePointer ( hVolume, 0, NULL, FILE_BEGIN );
WriteFile ( hVolume, &volumeHeader, 512, &dwBytesWritten, NULL );
how can I map only the first letter of my file??
I've tried these value for parameters :
1, // maximum object size (high-order DWORD)
1, // maximum object size (low-order DWORD)
(i don't know the difference between them).
is 1 the right parameter for an only 1 letter mapping?
#define FILENAME "c:\gibrish.bin"
#include <Windows.h>
#include <stdio.h>
int main()
{
HANDLE hFile;
LPCSTR pFileName = FILENAME;
hFile = CreateFileA(pFileName, // file name
FILE_MAP_ALL_ACCESS, // access type
0, // other processes can't share
NULL, // security
OPEN_EXISTING, // open only if file exists
FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hMapFile;
////////mapping here
hMapFile = CreateFileMappingA(hFile, // file handle
NULL, // default security
FILE_MAP_ALL_ACCESS, // read access
1, // maximum object size (high-order DWORD)
1, // maximum object size (low-order DWORD)
// 0 means map the whole file
"gibrishFile"); // name of mapping object, in case we
// want to share it
return 0;
}
how can I map only the first letter of my file??
I've tried these value for parameters :
1, // maximum object size (high-order DWORD)
1, // maximum object size (low-order DWORD)
these two parameters makes (a huge) number, if the number you want to give is 1 or any other under 2^32 the high-order DWORD must be 0. If you give 1 and 1 this means the number is 1*(2^32) + 1 = 4294967296, this is not compatible with only the first letter
From https://learn.microsoft.com/en-us/windows/desktop/winprog/windows-data-types :
DWORD A 32-bit unsigned integer. The range is 0 through 4294967295 decimal.
There is no parameters FILE_MAP_ALL_ACCESS in CreateFileMappingA msdn doc. The return value will always be failed, with GetLastError() return 87(ERROR_INVALID_PARAMETER). And the folder you are accessing is the "C:\\", If you don't have enough authority, CreateFileA will return a INVALID_HANDLE_VALUE and get error of 5(ERROR_ACCESS_DENIED).
CreateFileMappingA is used for creating space for mapping, but not the actual size you want to map. And then use MapViewOfFile() mapping into the address space of a calling process. And the size you want to map must <= the size you create.
I'm new with OpenCL and I'm trying to understand this example program written by Apple here.
The goal of the program is to calculate the square of each element of an input array and write the result in a new array.
You can see that the input array has dimension: 1024. The number of work groups is 1024 and the size of each of those is the max CL_KERNEL_WORK_GROUP_SIZE.
Can anybody explain me what's the point of using so many work-items in each work group if in the Kernel there's no get_local_id() call? Could they use 1 as the size of each work group? what would have been the difference?
Thanks.
Some code to show the point:
// Get the maximum work group size for executing the kernel on the device
//
err = clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_WORK_GROUP_SIZE, sizeof(local), &local, NULL);
// Execute the kernel over the entire range of our 1d input data set
// using the maximum number of work group items for this device
//
global = count;
err = clEnqueueNDRangeKernel(commands, kernel, 1, NULL, &global, &local, 0, NULL, NULL);
Your global work size is executed in chunks of local work size (in theory), if you set 1 as your local work group size, then it would execute only 1 thread in each local work group. On GPUs, work groups match to compute units - if you have a work group size of 1, your 1 thread may potentially occupy a whole compute unit. This is really, really horribly slow
I am a beginner in OpenCL and thus writing a simple program to double the elements of an array.
The kernel code is:-
__kernel void dataParallel(__global int* A, __global int* B)
{
int base = get_local_id(0);
B[base]=A[base]+A[base];
}
The local_work_size=32 as I am squaring 32 elements.
In my program I have declared an integer array which holds the elements to be squared.
int *A;
A=(int*)malloc(sizeof(int)*64);
for (i=0; i < 32; i++) { A[i] = i; }
platforms[i] stores the platform id, devices[j] stores the corresponding device id. Their types:
cl_platform_id* platforms;
cl_device_id* devices;
Creating context
cl_context context=clCreateContext(NULL,1,&devices[j],NULL,NULL,NULL);
Next comes the command queue
cl_command_queue cmdqueue=cmdqueue=clCreateCommandQueue(context,devices[j],NULL,&err);
Next I created 2 memory buffers, one to hold the input data and the other to hold the result.
cl_mem Abuffer,Bbuffer;
Abuffer=clCreateBuffer(context, CL_MEM_READ_WRITE ,32*sizeof(int),NULL,&err);
Bbuffer=clCreateBuffer(context, CL_MEM_READ_WRITE ,32*sizeof(int),NULL,&err);
Then I copied the data of array A to Abuffer
ret=clEnqueueWriteBuffer(cmdqueue, Abuffer, CL_TRUE, 0, 32*sizeof(int), A, 0, NULL, NULL);
printf("%d",ret);//output is 0 thus data written successfully into the buffer
The kernel code was then read into a character string source_str and the program was created.
kernelprgrm=clCreateProgramWithSource(context,1,(const char **)&source_str,(const size_t *)&source_size,&err);
if(!err)
{
printf("\nKernel program created successfully\n");
}//Outputs -Kernel program created successfully
I then built the program using:
ret=clBuildProgram(kernelprgrm,1,&devices[j],NULL,NULL,NULL);//returns CL_SUCCESS
Getting buildinfo next
ret=clGetProgramBuildInfo(kernelprgrm,devices[j], CL_PROGRAM_BUILD_STATUS ,0,NULL,&size);//Returns success
Creating kernel
kernel = clCreateKernel(kernelprgrm, "dataParallel", &ret);
printf("\nReturn kernel program=%d",ret);
if(!ret)
{
printf("\nProgram created successfully!\n");
}
//Outputs -Program created successfully!
Now comes the devil:-
ret=clSetKernelArg(kernel,0,sizeof(cl_mem),(void *) Abuffer);
printf("\nKernel argument 1 ret=%d",ret);
ret=clSetKernelArg(kernel,1,sizeof(cl_mem),(void *) Bbuffer);
printf("\nKernel argument 2 ret=%d",ret);
Both return -38 meaning CL_INVALID_MEM_OBJECT.
P.S.:As per the errors pointed out i.e. use &Abuffer instead of Abuffer in the argument and after making the necessary changes, both return 0
size_t global_item_size = 32;
size_t local_item_size = 32;
Also ret = clEnqueueNDRangeKernel(cmdqueue, kernel, 1, NULL,&global_item_size, &local_item_size, 0, NULL, NULL); returns 0.
Trying to get the result
ret = clEnqueueReadBuffer(cmdqueue, Bbuffer, CL_TRUE, 0, 32*sizeof(int), B, 0, NULL, NULL);`
printf("\nB:-\n");
for (t=0; t < 32; t++) {
printf("%d\t ", B[t]);
}
This returns buildstatus=0 with core getting dumped for my AMD GPU (running AMD Accelerated Parallel Processing platform) and NVIDIA GPU whereas it works perfectly fine if the selected device is CPU using Intel(R) OpenCL platform.
Also I tried getting the build log using:
cl_build_status *status=(cl_build_status *)malloc(sizeof(cl_build_status )*size);
clGetProgramBuildInfo(kernelprgrm,devices[j], CL_PROGRAM_BUILD_STATUS ,size,status,NULL);
printf("\nBuild status=%d\n",*status);
//Getting build info if not successful
clGetProgramBuildInfo(kernelprgrm,devices[i], CL_PROGRAM_BUILD_LOG ,0,NULL,&size);
char *buildlog=(char*)malloc(size);
clGetProgramBuildInfo(kernelprgrm,devices[i], CL_PROGRAM_BUILD_LOG ,size,buildlog,NULL);
printf("\n!!!!!!!!!!!!!!!!!!!!!Program ended!!!!!!!!!!!\n");
printf("\n\nBuildlog: %s\n\n",buildlog);
But it returns Buildlog: Compilation started
Compilation done
Linking started
Linking done
Device build started
Device build done
Kernel <dataParallel> was successfully vectorized (4)
Done.
Here's what the OpenCL 1.2 spec has to say about setting buffers as kernel arguments:
If the argument is a memory object (buffer, image or image array), the arg_value entry will be a pointer to the appropriate buffer, image or image array object.
So, you need to pass a pointer to the cl_mem objects:
ret=clSetKernelArg(kernel,0,sizeof(cl_mem),(void *) &Abuffer);
Why are you using clEnqueueTask? I think you should use clEnqueueNDRangeKernel if you have parallel work to do. Also, just set the global work size; pass NULL for the local work group size. 32x32 is larger than some devices can do.
I'm currently writing a cross platform library in C which includes gamepad support. Gamepad communication on windows is handled by both raw input and xinput, depending on the specific gamepad.
While xinput facilitates force feedback on xbox360 controllers, I have not found a way to do this using raw input. I have some gamepads that can give force feedback, but I cannot find a way to do this through raw input. Is there a way to do this?
I prefer not to use the directinput api, since it's deprecated and discouraged by Microsoft.
Edit:
Since I've implemented gamepads for a large part, maybe I can narrow down the question a bit. I suspect the amount of rumble motors in a gamepad can be found by reading the NumberOutputValueCaps of a HIDP_CAPS structure. This gives the correct result for all my test gamepads.
I'm using the funtcion HidP_GetUsageValue to read axis values, which works fine. Now I suspect calling HidP_SetUsageValue should allow me to change this output value, turning on the rumble motor. Calling this function fails, however. Should this function be able to access rumble motors?
HidP_SetUsageValue() only modifies a report buffer -- you need to first prepare an appropriately-sized buffer (which may be why the function was failing; input reports and output reports won't necessarily be the same size) then send it to the device before it will have any effect. MSDN suggests you can use HidD_SetOutputReport() for that purpose, but I had better luck with WriteFile(), following the sample code at: https://code.msdn.microsoft.com/windowshardware/HClient-HID-Sample-4ec99697/sourcecode?fileId=51262&pathId=340791466
This snippet (based on the Linux driver) lets me control the motors and LED on a DualShock 4:
const char *path = /* from GetRawInputDeviceInfo(RIDI_DEVICENAME) */;
HANDLE hid_device = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
assert(hid_device != INVALID_HANDLE_VALUE);
uint8_t buf[32];
memset(buf, 0, sizeof(buf));
buf[0] = 0x05;
buf[1] = 0xFF;
buf[4] = right_motor_strength; // 0-255
buf[5] = left_motor_strength; // 0-255
buf[6] = led_red_level; // 0-255
buf[7] = led_green_level; // 0-255
buf[8] = led_blue_level; // 0-255
DWORD bytes_written;
assert(WriteFile(hid_device, buf, sizeof(buf), &bytes_written, NULL));
assert(bytes_written == 32);
(EDIT: fixed buffer offsets)