I want to turn on a LED using C, meaning that I want to write on parallel port.
but the code doesn't work.
I use char ledStatus instead of BYTE ledStatus. is there any difference??
what is the problem in this code?
#include <windows.h>
#include <conio.h>
#include <staio.h>
#define LED_ON 1
int main()
{
HANDLE h;
unsigned long dwSize=1;
int success;
h = CreateFile(
L"LPT1",
GENERIC_WRITE, // access (read-write) mode
0, // share mode
NULL, // pointer to security attributes
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL // handle to file with attributes to copy
);
if (INVALID_HANDLE_VALUE == h)
{
//Handle Error
printf("CreateFile failed with error %d\n", GetLastError());
exit(1);
}
else
{
printf("CreateFile1 Successful\n");
}
char ledStatus;
// turn on LED
ledStatus = LED_ON;
success = WriteFile(h, &ledStatus, 1, &dwSize, NULL);
if (success)
{
printf("File Write Successful - %i bytes\n", dwSize);
}
else
{
printf("File Write Failed\n");
}
// close port
CloseHandle(h);
return 0;
}
Your question is very poorly documented, you didn't describe what signal you used or how you wired the LED. Lots of ways to get that wrong. But you have no hope of making it work with the standard Windows parallel driver. It was written to interface parallel devices like printers. Which requires handshaking to clock a byte to the device. The driver turns on the STROBE signal, the device must turn on the ACK signal to acknowledge it copied the byte. That of course doesn't happen, the WriteFile() calls only fill a buffer in the driver.
You'll need another driver to directly control the output lines, Inpout32 is a common choice. Find essential advice in Jan Axelson's book, also includes a link to Inpout32.
Related
I have used some code that implements manual MPI broadcast, basically a demo that unicasts an integer from root to all other nodes. Of course, unicasting to many nodes is less efficient than MPI_Bcast() but I just want to check how things work.
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void my_bcast(void* data, int count, MPI::Datatype datatype, int root, MPI::Intracomm communicator) {
int world_size = communicator.Get_size();
int world_rank = communicator.Get_rank();
if (world_rank == root) {
// If we are the root process, send our data to everyone
int i;
for (i = 0; i < world_size; i++) {
if (i != world_rank) {
communicator.Send(data, count, datatype, i, 0);
}
}
} else {
// If we are a receiver process, receive the data from the root
communicator.Recv(data, count, datatype, root, 0);
}
}
int main(int argc, char** argv) {
MPI::Init();
int world_rank = MPI::COMM_WORLD.Get_rank();
int data;
if (world_rank == 0) {
data = 100;
printf("Process 0 broadcasting data %d\n", data);
my_bcast(&data, 1, MPI::INT, 0, MPI::COMM_WORLD);
} else {
my_bcast(&data, 1, MPI::INT, 0, MPI::COMM_WORLD);
printf("Process %d received data %d from root process\n", world_rank, data);
}
MPI::Finalize();
}
What I noticed is that if I remove the check that the root doesn't send to itself,
if (i != world_rank) {
...
}
the program still works and doesn't block whereas the default behavior of MPI_Send() is supposed to be blocking i.e. to wait until the data has been received at the other end. But MPI_Recv() is never invoked by the root. Can someone explain why this is happening?
I run the code from the root with the following command (the cluster is set up on Amazon EC2 and using NFS as shared storage among the nodes and all machines have Open MPI 1.10.2 installed)
mpirun -mca btl ^openib -mca plm_rsh_no_tree_spawn 1 /EC2_NFS/my_bcast
The C file is compiled with
mpic++ my_bcast.c
and mpic++ version is 5.4.0.
The code is taken from www.mpitutorial.com
You are mistaking blocking for synchronous behaviour. Blocking means that the call does not return until the operation has completed. The standard send operation (MPI_Send) completes once the supplied buffer is free to be reused by the program. This means either that the message is fully in transit to the receiver or that it was stored internally by the MPI library for later delivery (buffered send). The buffering behaviour is implementation-specific, but most libraries will buffer messages the size of a single integer. Force the synchronous mode by using MPI_Ssend (or the C++ equivalent) to have your program hang.
Please note that the C++ MPI bindings are no longer part of the standard and should not be used in the development of new software. Use the C bindings MPI_Blabla instead.
I retrieve the serial number of the physical hard-drive using the function DeviceIoControl following the suggestions from Blacktempel in this post. Getting the number works fine in principle, but I (still) have trouble with the format of the serial number as it keeps changing from computer to computer and with time. Also I experienced a format change on some computers between running the program as normal user or as admin.
For example, I retrieved a number with the following format:
WD-WCAZAF632086
when I tested the program first and after a few weeks it looks like:
2020202057202d4443575a414641333630323638
This is still the same number, only the characters have been replaced by their hex codes and swapped pair-wise. I've encountered different formats like a normal string with the characters exchanged pair-wise. Among other values, I need to check this number to verify if a software license is valid for a certain computer. Having an instable and unknown format is annoying and if the format changes to something I'm not yet aware of, I risk that the software license check fails although the license is still valid.
Does anyone know how to get the serial number in a stable format, or how to predict the format so it can be adapted for comparison?
Here is minimal C++ example of code that I used to retrieve the serial number of the first physical disc. I build it using Visual Studio 2015:
#include "stdafx.h"
#include "Windows.h"
#include <string>
#include <vector>
#include <iostream>
bool GetDeviceString(std::string &serialnumber)
{
HANDLE deviceHandle = CreateFileW(L"//./PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); // Get Handle to device
if (deviceHandle == INVALID_HANDLE_VALUE) // Check if Handle is valid
return false;
STORAGE_PROPERTY_QUERY query{};
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
DWORD dwBytesReturned;
if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
&storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL))
{
}
// Alloc the output buffer
const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
std::vector<BYTE> pOutBuffer(dwOutBufferSize,0);
if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
pOutBuffer.data(), dwOutBufferSize,
&dwBytesReturned, NULL))
{
// handle error, do cleanup and return
}
STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer.data();
const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
if (dwSerialNumberOffset != 0)
{
// Finally, get the serial number
serialnumber = (char*)(pOutBuffer.data() + dwSerialNumberOffset);
}
}
int main()
{
std::string serialnumber;
if (GetDeviceString(serialnumber))
{
std::cout << "serial number of first disc: " << serialnumber << std::endl;
}
else
{
std::cout << "Failed!" << std::endl;
}
std::cin.ignore();
return 0;
}
I've been experimenting with Overlapped IO feature of Win32 API, namely ReadFileEx and WriteFileEx functions.
Here is a simplest example:
#include <iostream>
#include <string>
#include <Windows.h>
const DWORD blockSize = 512;
char buffer[blockSize];
bool done = false;
OVERLAPPED overlapped;
void Completion(DWORD error, DWORD read, LPOVERLAPPED overlapped) {
}
int _tmain(int argc, _TCHAR* argv[])
{
std::wstring fileName;
std::wcout << "Enter file name: ";
std::getline(std::wcin, fileName);
HANDLE file = CreateFile(
fileName.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if (file == INVALID_HANDLE_VALUE) {
std::wcout << "Error while opening file: " << GetLastError() << std::endl;
std::cin.get();
return -1;
}
overlapped.Offset = overlapped.OffsetHigh = 0;
ReadFileEx(file, buffer, blockSize, &overlapped, (LPOVERLAPPED_COMPLETION_ROUTINE) &Completion);
while (!done)
SleepEx(1000, TRUE);
return 0;
}
As you can see, I'm starting overlapped reading with ReadFileEx and waiting for it to finish using SleepEx. Although Completion has empty body and the program should hang forever after reading first block, it does something completely different. In fact, it raises AccessViolation with code 0xC0000005 on the first call to SleepEx. This happens on Windows machines with Win 7 and Win Vista I've tried, including fresh 64 bit virtual machine with Windows 7. But, curiously, it does not fail on one Windows 8.1 machine and runs just as expected. This was compiled with Visual Studio 2010, but I don't think it matters.
I can not understand what have I done wrong, so if anyone knows the answer, please help me.
The callback must be of the following form, as stated clearly in the documentation:
VOID CALLBACK FileIOCompletionRoutine(
_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
);
Your function has the wrong calling convention. Your cast does not change that. It is simply a way for you to stop the compiler rejecting your ill-formed program. Don't lie to the compiler. Correct the function declaration by adding the CALLBACK calling convention.
I have been looking for some time but have not found anywhere near sufficient documentation / examples on how to use the CryptoAPI that comes with linux in the creation of syscalls / in kernel land.
If anyone knows of a good source please let me know, I would like to know how to do SHA1 / MD5 and Blowfish / AES within the kernel space only.
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/err.h>
#include <linux/scatterlist.h>
#define SHA1_LENGTH 20
static int __init sha1_init(void)
{
struct scatterlist sg;
struct crypto_hash *tfm;
struct hash_desc desc;
unsigned char output[SHA1_LENGTH];
unsigned char buf[10];
int i;
printk(KERN_INFO "sha1: %s\n", __FUNCTION__);
memset(buf, 'A', 10);
memset(output, 0x00, SHA1_LENGTH);
tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
desc.tfm = tfm;
desc.flags = 0;
sg_init_one(&sg, buf, 10);
crypto_hash_init(&desc);
crypto_hash_update(&desc, &sg, 10);
crypto_hash_final(&desc, output);
for (i = 0; i < 20; i++) {
printk(KERN_ERR "%d-%d\n", output[i], i);
}
crypto_free_hash(tfm);
return 0;
}
static void __exit sha1_exit(void)
{
printk(KERN_INFO "sha1: %s\n", __FUNCTION__);
}
module_init(sha1_init);
module_exit(sha1_exit);
MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Me");
There are a couple of places in the kernel which use the crypto module: the eCryptfs file system (linux/fs/ecryptfs/) and the 802.11 wireless stack (linux/drivers/staging/rtl8187se/ieee80211/). Both of these use AES, but you may be able to extrapolate what you find there to MD5.
Another good example is from the 2.6.18 kernel source in security/seclvl.c
Note: You can change CRYPTO_TFM_REQ_MAY_SLEEP if needed
static int
plaintext_to_sha1(unsigned char *hash, const char *plaintext, unsigned int len)
{
struct crypto_tfm *tfm;
struct scatterlist sg;
if (len > PAGE_SIZE) {
seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d "
"characters). Largest possible is %lu "
"bytes.\n", len, PAGE_SIZE);
return -EINVAL;
}
tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP);
if (tfm == NULL) {
seclvl_printk(0, KERN_ERR,
"Failed to load transform for SHA1\n");
return -EINVAL;
}
sg_init_one(&sg, (u8 *)plaintext, len);
crypto_digest_init(tfm);
crypto_digest_update(tfm, &sg, 1);
crypto_digest_final(tfm, hash);
crypto_free_tfm(tfm);
return 0;
}
Cryptodev-linux
https://github.com/cryptodev-linux/cryptodev-linux
It is a kernel module that exposes the kernel crypto API to userspace through /dev/crypto .
SHA calculation example: https://github.com/cryptodev-linux/cryptodev-linux/blob/da730106c2558c8e0c8e1b1b1812d32ef9574ab7/examples/sha.c
As others have mentioned, the kernel does not seem to expose the crypto API to userspace itself, which is a shame since the kernel can already use native hardware accelerated crypto functions internally.
Crypto operations cryptodev supports: https://github.com/nmav/cryptodev-linux/blob/383922cabeea7dca354415e8c590f8e932f4d7a8/crypto/cryptodev.h
Crypto operations Linux x86 supports: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/crypto?id=refs/tags/v4.0
The best place to start is Documentation/crytpo in the kernel sources. dm-crypt is one of the many components that probably uses the kernel crypto API and you can refer to it to get an idea about usage.
how to do SHA1 / MD5 and Blowfish / AES within the kernel space only.
Example of hashing data using a two-element scatterlist:
struct crypto_hash *tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
if (tfm == NULL)
fail;
char *output_buf = kmalloc(crypto_hash_digestsize(tfm), GFP_KERNEL);
if (output_buf == NULL)
fail;
struct scatterlist sg[2];
struct hash_desc desc = {.tfm = tfm};
ret = crypto_hash_init(&desc);
if (ret != 0)
fail;
sg_init_table(sg, ARRAY_SIZE(sg));
sg_set_buf(&sg[0], "Hello", 5);
sg_set_buf(&sg[1], " World", 6);
ret = crypto_hash_digest(&desc, sg, 11, output_buf);
if (ret != 0)
fail;
One critical note:
Never compare the return value of crypto_alloc_hash function to NULL for detecting the failure.
Steps:
Always use IS_ERR function for this purpose. Comparing to NULL does not capture the error, hence you get segmentation faults later on.
If IS_ERR returns fail, you possibly have a missing crypto algorithm compiled into your kernel image (or as a module). Make sure you have selected the appropriate crypto algo. form make menuconfig.
I need to access the partition table of a USB stick and change the first byte of partition 0 to make it bootable. And I also want to copy a bin file to a specific address of that USB drive. So can any one tell me how to perform these kind of tasks?
I badly in need of some examples... If you could provide any links of such kinds of works it would be great. I am working in C.
I am in the beginning stage. Here is my code:
// DeviceIoControl.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
BOOL GetMBR(PARTITION_INFORMATION *pdg)
{
HANDLE hDevice; // handle to the drive to be examined
BOOL bResult; // results flag
DWORD junk; // discard results
hDevice = CreateFile(TEXT("\\\\.\\H:"), // drive to open
GENERIC_READ | GENERIC_WRITE, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL // do not copy file attributes
);
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("CreateFile() failed!\n");
return (FALSE);
}
bResult = DeviceIoControl(
hDevice, // device to be queried
IOCTL_DISK_GET_PARTITION_INFO, // operation to perform
NULL, 0, // no input buffer
pdg, sizeof(*pdg), // output buffer
&junk, // # bytes returned
(LPOVERLAPPED) NULL // synchronous I/O
);
CloseHandle(hDevice);
return (bResult);
}
int _tmain(int argc, _TCHAR* argv[])
{
PARTITION_INFORMATION pdg; // disk drive geometry structure
BOOL bResult; // generic results flag
ULONGLONG DiskSize; // size of the drive, in bytes
bResult = GetMBR(&pdg);
if (bResult)
{
printf ("BootIndicator %lld\n", pdg.BootIndicator);
printf ("HiddenSectors %lld\n", pdg.HiddenSectors);
printf ("PartitionLength %u\n", pdg.PartitionLength);
printf ("PartitionNumber %u\n", pdg.PartitionNumber);
printf ("PartitionType %x\n", pdg.PartitionType);
printf ("RecognizedPartition %s\n", pdg.RecognizedPartition);
printf ("RewritePartition %ld.\n", pdg.RewritePartition);
printf ("StartingOffset %lld\n", pdg.StartingOffset);
}
else
{
printf ("PARTITION INFORMATION failed. Error %ld.\n", GetLastError ());
}
getchar();
return ((int)bResult);
}
Do you have to do it in code? You can use the built-in diskpart tool to make a USB drive bootable by following this tutorial.