MFRC 522 Authentication RESET on Arduino IDE with ESP32 - rfid

I've been tinkering with the MFRC-522 (RC-522) RFID module for a project.
I'm testing authentication using an old key to check if the RFID's key A for a sector (in my case, Sector 2) is different from the original, if it was, then I would continue, if not I would like to "register" the card by changing the key.
I was caught at the beginning on checking different keys authentication, if I tested a working key and then an incorrect key, it works as expected, but if I test with the incorrect key first, it doesn't allow even the correct key to authenticate.
If I ran the code below everything in serial is
PCD_Authenticate() failed NEW(read): Timeout in communication.
PCD_Authenticate() failed OLD(read): Timeout in communication.
repeatedly but if I flipped old() and neww() I get
OLD WORKS
PCD_Authenticate() failed NEW(read): Timeout in communication.
Why does it work as such?
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 22 // Configurable, see typical pin layout above
#define SS_PIN 21 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
MFRC522::MIFARE_Key old_key = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
MFRC522::MIFARE_Key new_key = {0x23,0x54,0x64,0x3a,0x32,0x66};
void setup() {
Serial.begin(115200); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522
delay(4); // Optional delay. Some board do need more time after init to be ready, see Readme
mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details
Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}
void loop() {
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
neww();
old();
}
void old(){
//authentication of the desired block for access
byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 15, &old_key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed OLD(read): ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)status));
return;
}else {Serial.println("OLD WORKS");}
//delay(1000);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
void neww() {
//authentication of the desired block for access
byte status_new = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 15, &new_key, &(mfrc522.uid));
if (status_new != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed NEW(read): ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)status_new));
return;
} else {Serial.println("NEW WORKS");}
//delay(1000);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
}

So, after reading the datasheet extra hard I came to the conclusion that the state of the card was not ready for the next read, so I came with a fire-all-guns solution that helped my case, The Serial prints are for debugging so if using the code feel free to comment them out.
bool reselect_Card() {
//-------------------------------------------------------
// Can also be used to see if card still available,
// true means it is false means card isnt there anymore
//-------------------------------------------------------
byte s;
byte req_buff[2];
byte req_buff_size=2;
mfrc522.PCD_StopCrypto1();
s = mfrc522.PICC_HaltA();
Serial.print("Halt Status: ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
delay(100);
s = mfrc522.PICC_WakeupA(req_buff,&req_buff_size);
Serial.print("Request: ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
Serial.print("ATQA : ");
Serial.println(dump_byte_array_to_string(req_buff,req_buff_size));
delay(100);
s = mfrc522.PICC_Select( &(mfrc522.uid),0);
Serial.print("Selected : ");
Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
if( mfrc522.GetStatusCodeName((MFRC522::StatusCode)s) == F("Timeout in communication.") ) { return false;}
return true;
}

Related

Issues while reading Writting USB data

I am new to Linux operating system, i am trying to interface GSM module with USB,i interfaced USB with GSM module successfully, but i have problem while reading the data from GSM module, i can able to write data to GSM module but while reading its too difficult for me, some time i can able to read data but some time i can't able to read data, here i copy and pasted my code, please go through the code and please let me where i am failing to read data,
i need to write data normally to USB port and data should be read on interrupt based
USB configuration
int init_ttyusb0(int speed,int parity)
{
fd=open("/dev/ttyUSB1",O_RDWR|O_NDELAY|O_NOCTTY|O_APPEND,S_IRWXU|S_IRWXG|S_IRWXO);|O_NOCTTY|O_SYNC|O_NDELAY);
perror("open");
if(fd==-1)
{
perror("open");
printf("open usb driver failed\n");
//close(fd);
return 1;
}
saio.sa_handler= signal_handler_IO;
saio.sa_flags=0;
saio.sa_restorer=NULL;
sigaction(SIGIO,&saio,NULL);
fcntl(fd,F_SETFL,FNDELAY);
fcntl(fd,F_SETOWN,getpid());
tcgetattr(fd,&tty);
perror("tcgetattr");
cfsetospeed(&tty,speed);
perror("cfsetospeed");
cfsetispeed(&tty,speed);
perror("cfsetispeed");
tty.c_cflag=(tty.c_cflag&~CSIZE)|CS8; // 8bit character
tty.c_iflag&=~IGNBRK;
// tty.c_lflag=0; // No signaling break process
// tty.c_oflag=0; //No remaping no delay
tty.c_cc[VMIN]=0; // read dosen't block
tty.c_cc[VTIME]=10; //0.5 seconds
tty.c_iflag&=~(IXON|IXOFF|IXANY);
tty.c_cflag|=CLOCAL; // igniore modem controls
tty.c_cflag|=CREAD;
tty.c_cflag&=~(PARENB|PARODD);
tty.c_cflag&=~CSTOPB;
tty.c_cflag&=~CRTSCTS;
tty.c_cflag&=~ICANON; // Disabling cananicle from disbling newline
tty.c_cflag&=~ISIG; // Disabling interrupt signaling bits
// tty.c_iflag&=~(IXON|IXOFF|IXANY); // Disabling software flow control
tty.c_lflag&=~ECHO;
tty.c_lflag&=~ECHOE;
tty.c_lflag&=~ECHONL;
tty.c_lflag&=~(IXON|IXOFF|IXANY);
tty.c_oflag&=~OPOST;
tcsetattr(fd,TCSANOW,&tty);
perror("tcsetattr");
printf("UART configured.....................\n");
}
Interrupt handler
-----------------------
void signal_handler_IO(int status)
{
static int gsm_count
read(fd,&zfc_buffer[gsm_count],sizeof(zfc_buffer));
printf("%s\n",zfc_buffer);
memset(zfc_buffer,0,sizeof(zfc_buffer));
fcntl(fd,F_SETFL,!(O_ASYNC));
}
int main(void)
{
int init_ttyusb0(B9600,0)
while(1)
{
printf("\n eneter option > ");
scanf("%d",&operation);
int m=26;
switch(operation)
{
case 0:
memset(buf_rcv,0,sizeof(buf_rcv));
buf[0]='A';
buf[1]='T';
buf[2]='\r';
buf[3]='\0';
write(fd,"AT\r",3);
usleep((3+25)*100);
fcntl(fd,F_SETFL,O_ASYNC); // Enabling interrupt after write
usleep((3+25)*100);
perror("write");
break;
case 1:
write(fd,"AT+CFUN=1\r",10);
usleep(175000);
fcntl(fd,F_SETFL,O_ASYNC);// Enabling interrupt after write
break;
case 2:
memset(buf,0,sizeof(buf));
strcpy(buf,"AT+CCID\r");
write(fd,"AT+CPIN?\r",9);
usleep(150000);
fcntl(fd,F_SETFL,O_ASYNC);// Enabling interrupt after write
break;
}

Errors creating a multithreaded named pipe server with Administrator only access on windows c++

Im trying to create a multithreaded namedpipe server as outlined in the msdn sample here https://learn.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server but Im trying to restrict the namedpipe to access by adminstrators group members only.
The example works correctly when no SECURITY_ATTRIBUTES structure is specified but when an SA is specified the first call is successful, but following calls to CreateNamedPipe fail as long as the first pipe is listening or communicating with a client. The create call fails, usually with ACCESS_DENIED, but sometimes with error 1305 The revision level is unknown. When the first pipe closes due to client disconnecting the following call will be successful for the next createnamedpipe call but will in turn fail once that pipe has a client.
I have tried multiple values for the grfInheritance field with no avail. This is my first adventure into explicitly specifying SECURITY so forgive me if I have missed something obvious. Note that in the Function that calls createnamedpipe I create a new SA structure with each create attempt but I have also tried creating one and sharing it outside the create loop.
Relevant code follows:
function that creates the pipe:
HRESULT DapiSettingsSvr::DapiSettingsListener()
{
while(m_run)
{
//find an unused control array member. If they are all used we have max connection so dont create a pipe.
UINT connectId = 0;
for (connectId; connectId < MAX_CONNECTIONS; connectId++)
{
if (m_controlArray[connectId].inuse == false)
break;
}
SECURITY_ATTRIBUTES sa;
HRESULT hr = InitializeSecurity(&sa);
if (FAILED(hr))
{
return hr;
}
if (connectId < MAX_CONNECTIONS)
{
HANDLE hpipe;
hpipe = CreateNamedPipe(
lpszPipename, // pipe name
PIPE_ACCESS_DUPLEX, // read/write access
PIPE_TYPE_BYTE | // byte bipe
PIPE_READMODE_BYTE | // read as bytes
PIPE_WAIT | // do not return until data is recieved
PIPE_REJECT_REMOTE_CLIENTS, // no remote connections
MAX_CONNECTIONS, // max. instances
OUTPUT_BUFFER_SIZE, // output buffer size
INPUT_BUFFER_SIZE, // input buffer size
0, // client time-out
&sa); // default security attribute
// CleanUpSecurityResources();
if (hpipe == INVALID_HANDLE_VALUE)
{
swprintf(logbuffer, ARRAYSIZE(logbuffer), L"CreateNamedPipe failed, GLE=%d.\n", GetLastError());
DapiSettingLogger(logbuffer);
}
else
{
m_controlArray[connectId].inuse = true;
m_controlArray[connectId].pThis = this;
m_controlArray[connectId].connectId = connectId;
m_controlArray[connectId].pipehandle = hpipe;
swprintf(logbuffer, ARRAYSIZE(logbuffer), L"\nPipe Server: Main thread awaiting client connection on %s\n", lpszPipename);
DapiSettingLogger(logbuffer);
// block until a client tries to connect.success is non zero. However a client can connect between the create call and ConnectNamedPipe call.
// In this case ConnectNamedPipe returns zero but GLE = ERROR_PIPE_CONNECTED and a valid connection exists. Check for this case.
fConnected = ConnectNamedPipe(hpipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (fConnected)
{
// Create a thread for this client.
m_controlArray[connectId].threadHandle = CreateThread(
NULL, // no security attribute
0, // default stack size
WorkerInstance, // thread proc
(LPVOID)&m_controlArray[connectId], // thread parameter
0, // not suspended
&m_controlArray[connectId].threadId); // returns thread ID
if (m_controlArray[connectId].threadHandle == NULL)
{
swprintf_s(logbuffer, ARRAYSIZE(logbuffer), L"CreateThread failed, GLE=%d.\n", GetLastError());
DapiSettingLogger(logbuffer);
CloseHandle(m_controlArray[connectId].pipehandle);
ZeroMemory(&m_controlArray[connectId], sizeof(WORKER_INFO));
}
}
else
{
// The client could not connect, so close the pipe.
CloseHandle(m_controlArray[connectId].pipehandle);
ZeroMemory(&m_controlArray[connectId], sizeof(WORKER_INFO));
}
} //else valid connection
}
else
{
DapiSettingLogger((LPWSTR) L"Max Connections reached\n");
}
}
return S_OK;
}
Function that creates the SA
HRESULT DapiSettingsSvr::InitializeSecurity(SECURITY_ATTRIBUTES* psa)
{
HRESULT result = S_OK;
DWORD res, error;
EXPLICIT_ACCESS ea[1];
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
// Create a SID for the BUILTIN\Administrators group.
if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&m_pAdminSID))
{
error = GetLastError();
swprintf(logbuffer, ARRAYSIZE(logbuffer), L"AllocateAndInitializeSid Error %u\n", error);
DapiSettingLogger(logbuffer);
result = HRESULT_FROM_WIN32(error);
goto Cleanup;
}
ea[0].grfAccessPermissions = GENERIC_ALL;
ea[0].grfAccessMode = GRANT_ACCESS;
ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; //changing
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR)m_pAdminSID;
// Create a new ACL that contains the new ACE.
res = SetEntriesInAcl(1, ea, NULL, &m_pACL);
if (ERROR_SUCCESS != res)
{
swprintf(logbuffer, ARRAYSIZE(logbuffer),L"SetEntriesInAcl Error %u\n", res);
DapiSettingLogger(logbuffer);
result = HRESULT_FROM_WIN32(res);
goto Cleanup;
}
// Initialize a descriptor Use localalloc as it allows memory moving without changing handle value
m_pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == m_pSD)
{
error = GetLastError();
swprintf(logbuffer, ARRAYSIZE(logbuffer), L"LocalAlloc Error %u\n", error);
result = HRESULT_FROM_WIN32(error);
goto Cleanup;
}
if (!InitializeSecurityDescriptor(m_pSD,
SECURITY_DESCRIPTOR_REVISION))
{
error = GetLastError();
swprintf(logbuffer, ARRAYSIZE(logbuffer), L"InitializeSecurityDescriptor Error %u\n", error);
result = HRESULT_FROM_WIN32(error);
goto Cleanup;
}
// Add the ACL to the security descriptor.
if (!SetSecurityDescriptorDacl(m_pSD,
TRUE, // bDaclPresent flag
m_pACL,
FALSE)) // not a default DACL
{
error = GetLastError();
swprintf(logbuffer, ARRAYSIZE(logbuffer), L"SetSecurityDescriptorDacl Error %u\n", error);
result = HRESULT_FROM_WIN32(error);
goto Cleanup;
}
Cleanup:
if (FAILED(result))
{
CleanUpSecurityResources();
}
else
{
// Initialize a security attributes structure.
psa->nLength = sizeof(SECURITY_ATTRIBUTES);
psa->lpSecurityDescriptor = m_pSD;
psa->bInheritHandle = TRUE; /// NOTE I have toyed with this value also
}
return result;
}
Any input on what Im doing incorrectly would be greatly appriciated!!
Thanks!
According to Named Pipe Security and Access Rights,
In addition to the requested access rights, the DACL must allow the
calling thread FILE_CREATE_PIPE_INSTANCE access to the named pipe.
Ok, I figured this out. Im going to mark YangXiaoPo's answer as correct as this pointed me in the right direction but for clarification GENERIC_ALL already includes the right to FILE_CREATE_PIPE_INSTANCE or at least thats what my testing indcates. So setting the EXPICIT_ACCESS structure field to ea[0].grfAccessPermissions = GENERIC_ALL | FILE_CREATE_PIPE_INSTANCE; does not resolve this issue.
The answer lies in the fact that I was running the PipeServer program from within visual studio ( debug ) and thus as a generic user. So the first time through the loop a pipe gets created and the SA with the local administrators group ACE is then applied to the pipe.
So we get a pipe created in the listening state. As soon as a client connects the working thread is created and then the the while(m_run) loop does another iteration and tries to create a new pipe instance. This attempt fails ( actually a looping fail ) because the security attribute with the administrators only ACL is now looked at and the program is not running as an administrator. As soon as the first client disconnects the working thread closes the pipe handle ( effectively destroying the pipe ) and then in the next iteration a pipe is again created.
Running the program as Administrator ( or starting Visual studio as Admin and then debugging ) resolves the issue, though I think a fully correct solution would be to create a second ACE that specified Creator Owner in addition to Admin for the SA DACL.
Thanks!!

Struggling to get ESP8266 on Arduino Uno working reliably with AT communication

I am struggling to get ESP8266 connected to an Arduino Uno working reliably as a webserver. The firmware of my ESP8266 is 1.1.1 - I don't have the option (or knowledge) to update it at the moment. Below is my code. It works, barely, if I serve a small string. However, it usually closes the connection or just loads forever (crashes?) if I try to load the page from the browser three or four times. Ultimately I need to serve a webpage with json embedded in it that will load a second page served by the esp8266, a json file. I have a working demo of that but it crashes after a few retrievals. I understand that my html page is too long for strings so have been attempting to shift across to PROGMEM, initially testing with just a short string. I am storing and retrieving that correctly (I think, at least I can Serial.print it) but as soon as I try to write it to the ESP8266 I get a never ending load in my browser.
Where am I going wrong here? Is it the string/PROGMEM that is causing the issues or is there something else I'm missing in the AT commands (like some sort of ping to keep the connection open)?
//load softserial library
#include <SoftwareSerial.h>
#include <avr/pgmspace.h>
//set a boolean constant variable to true
//#define DEBUG true
const boolean DEBUG = true;
//RX (pin 2) goes to TX on esp8266, TX (pin 3) goes to RX on esp8266
SoftwareSerial esp8266(2, 3);
//input from the photoresistor
//int photoresistorpin = 0;
//create a PROGMEM variable
//String WEBPAGE = "hello";
static const char PROGMEM WEBPAGE[] = {"hello"};
/*
static const char WEBPAGE[] PROGMEM = R"rawliteral(
<html>
<head>
<meta name="viewport" content="width=device-width, minimumscale=1, maximum-scale=1, initial-scale=1">
</head>
<h1>Light:</h1><div id="light"></div>
<script>
function loadDoc()
{
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200)
{
var obj = JSON.parse(this.responseText);
document.getElementById('light').innerHTML = obj.data[0].datavalue;
}
};
xhttp.open('GET', 'data.json', true); xhttp.send();
}
var timedEvent = setInterval(function() { loadDoc(); }, 5000);
</script>
</body>
</html>
)rawliteral";
*/
//const int WEBPAGE_len = sizeof(WEBPAGE)/sizeof(WEBPAGE[0]);
void setup()
{
//open the serial port
Serial.begin(115200);
//print setup started in the serial monitor
Serial.println("Setup started");
//start esp8266 module (note: your esp's baud rate might be different)
esp8266.begin(115200);
//reset esp8266 module
senddata("AT+RST\r\n", 2000, DEBUG);
//set esp8266 as access point mode
//1 = Station mode (client)
//2 = Access point mode (host)
//3 = Access point mode + Station mode
senddata("AT+CWMODE=2\r\n", 1000, DEBUG);
//get ip address for esp8266
senddata("AT+CIFSR\r\n", 2000, DEBUG);
//configure esp8266 for multiple connections
senddata("AT+CIPMUX=1\r\n", 1000, DEBUG);
//turn on esp8266 server on port 80
senddata("AT+CIPSERVER=1,80\r\n", 1000, DEBUG);
//setup completed
Serial.println("Setup done");
}
void loop()
{
//take a reading from the photoresistor
//int lightval = analogRead(photoresistorpin);
int lightval = random(1000);
//to test
//Serial.println(lightval);
//is the esp8266 sending a message
if (esp8266.available())
{
//if received data from esp8266
if (esp8266.find("+IPD,"))
{
//subtract 48 because the read() function returns the ASCII decimal
//value and 0 (the first decimal number) starts at 48
int connectionid = esp8266.read() - 48;
//Serial.println("");
//Serial.println("*****");
//Serial.print("string = ");
//read the url sent by the client, look for the variable (/)
String msg;
esp8266.find("/");
delay(100);
msg = esp8266.readStringUntil(' ');
String pathrequested = msg.substring(0);
Serial.println("*****");
Serial.println(pathrequested);
Serial.println("*****");
//create a senddata string to send the webpage to the esp8266
String cipsend = "AT+CIPSEND=" + String(connectionid) + ",";
//cipsend += WEBPAGE.length();
cipsend += strlen_P(WEBPAGE);
cipsend += "\r\n";
Serial.println(cipsend);
char buffer[1000];
strcpy_P(buffer, WEBPAGE);
Serial.println(buffer);
//senddata(cipsend, 500, DEBUG);
//senddata(WEBPAGE, 500, DEBUG);
senddata(buffer, 500, DEBUG);
//create a string closecommand with the connection id and send it
String closecommand = "AT+CIPCLOSE=" + String(connectionid) + "\r\n";
senddata(closecommand, 500, DEBUG);
//increment the count
//count++;
}
}
}
void senddata(String command, const int timeout, boolean debug)
{
//send the received command to the esp8266
esp8266.print(command);
//set int variable to the number of millisends since Arduino began
long int time = millis();
//while the time and the timeout is less than the number of millisends since Arduino began
while((time + timeout) > millis())
{
//while the esp8266 is sending messages
while(esp8266.available())
{
//display output in the serial window
Serial.write(esp8266.read());
}
}
}
Assuming that "get a never ending load in my browser" means no display in the browser - check the following:
1. Get rid of String amd String constructors (+=) in your code and replace it with a fixed char array for the building of messages. Read more: https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/
2. My experience with the AT interface was - more than 9600 baud is not reliable and this is not sufficient for doing what you want.
3. If your Esp module has min 512kb (most likely up to 4Mb) host your code there and use the UNO only as sigmal receiver/sender from the attached hardware/ sensors. Save yourself a lot of trouble and problems - most of the examples with AT com are not really working and more of a pain in the ***. I ditched the AT interface within 2 days and never in the last 4 years missed anything. By flashing code to the Esp module you also have full control and visibility on whats going on due to the debug possiblitie AND you can even host html/css/js on the File system there (LittleFS / SPIFFS)

Windows Filtering Platform Network Slowdown Due to Spinlock

I am writing a Windows Filtering Platform Kernel Mode Driver, the goal of the driver is to capture all traffic on a particular layer, and communicate this traffic back down to user-mode so that it can be further analyses. The driver never needs to block any traffic, the classifyOut is always set to FWP_ACTION_CONTINUE.
The following code is used in my Classify function to queue up the packets that are received.
classifyOut->actionType = FWP_ACTION_CONTINUE;
do
{
if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
{
break;
}
if (layerData != NULL)
{
PNET_BUFFER_LIST netBufferList = (PNET_BUFFER_LIST) layerData;
PNET_BUFFER netBuffer = NET_BUFFER_LIST_FIRST_NB(netBufferList);
if (packetQueueSize >= 2048)
{
ExInterlockedRemoveHeadList(&packetQueue, &packetQueueLock);
packetQueueSize--;
}
ULONG netBufferSize = NET_BUFFER_DATA_LENGTH(netBuffer);
PACKET_ITEM* allocatedPacket = InitalizePacketItem(
netBuffer,
netBufferSize
);
if (allocatedPacket == NULL)
{
classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
break;
}
ExInterlockedInsertTailList(
&packetQueue,
&allocatedPacket->listEntry,
&packetQueueLock
);
allocatedPacket = NULL;
packetQueueSize++;
}
} while (FALSE);
The PACKET_ITEM struct is defined as the following
typedef struct _PACKET_ITEM {
LIST_ENTRY listEntry;
PVOID data;
ULONG dataLen;
} PACKET_ITEM;
I am using the inverted call model to communicate this packet data from kernel mode to user mode. The following code is used in the kernel driver once it detects the correct IOCTL has been sent.
status = WdfRequestRetrieveOutputBuffer(request, 0, &buffer, &bufferSize);
if (!NT_SUCCESS(status))
{
break;
}
PLIST_ENTRY listEntry = ExInterlockedRemoveHeadList(&packetQueue, &packetQueueLock);
if (listEntry == NULL)
{
break;
}
PACKET_ITEM* packetItem = CONTAINING_RECORD(
listEntry,
struct _PACKET_ITEM,
listEntry
);
RtlCopyMemory(
buffer,
packetItem->data,
packetItem->dataLen);
status = STATUS_SUCCESS;
WdfRequestCompleteWithInformation(
request,
status,
packetItem->dataLen
);
FreePacketItem(packetItem);
This code seems to slow the network down greatly after a short while, causing timeouts when trying to load websites in a web browser, for example.
I assume this is being caused by the spinlocks and the sheer volume of packets being transferred across the network that are being captured by this driver.
My questions are the following
Is it likely the spinlock is definitely causing my problems here? If so
Is it possible to set the classifyOut->actionType immediately and return this value before allocating any memory to copy the data into my queue. I assume this would prevent the slow down from happening?
What else should I be doing differently to prevent this?
If not,
What is causing the issue with the slow down here?

RegisterEventHotKey CMD+TAB in Mountain Lion

According to this post:
ShortcutRecorder record CMD+Tab
calling setCanCaptureGlobalHotKeys:YES on the ShortCutRecorder control should allow you to capture CMD+TAB. However, it doesn't seem to work. I created this small app myself to see whats going on:
OSStatus myHotKeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData)
{
NSLog(#"YEAY WE DID A GLOBAL HOTKEY");
return noErr;
}
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
EventHotKeyRef myHotKeyRef;
EventHotKeyID myHotKeyID;
EventTypeSpec eventType;
eventType.eventClass = kEventClassKeyboard;
eventType.eventKind = kEventHotKeyPressed;
myHotKeyID.signature = 'mhk1';
myHotKeyID.id = 1;
InstallApplicationEventHandler(&myHotKeyHandler, 1, &eventType, NULL, NULL);
OSStatus status = RegisterEventHotKey(kVK_Tab,
cmdKey,
myHotKeyID,
GetApplicationEventTarget(),
0,
&myHotKeyRef);
NSLog(#"status:%d", status);
}
#end
If I use cmdKey + optionKey, then it does work.
Is there another way to capture CMD+TAB in my own application on Mountain Lion? CMD+OPTION+TAB is not good enough for me.
Things have changed a bit since that question was asked in 2010! ⌘⇥ is detected by Dock.app with an Event Tap, and that event no longer makes it back to the application.
You can still hook ⌘⇥, but you need to beat Dock to it with an Event Tap yourself. Here's some example code, courtesy osxbook.com:
// alterkeys.c
// http://osxbook.com
//
// Complile using the following command line:
// gcc -Wall -o alterkeys alterkeys.c -framework ApplicationServices
//
// You need superuser privileges to create the event tap, unless accessibility
// is enabled. To do so, select the "Enable access for assistive devices"
// checkbox in the Universal Access system preference pane.
#include <ApplicationServices/ApplicationServices.h>
// This callback will be invoked every time there is a keystroke.
//
CGEventRef
myCGEventCallback(CGEventTapProxy proxy, CGEventType type,
CGEventRef event, void *refcon)
{
// Paranoid sanity check.
if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp))
return event;
// The incoming keycode.
CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(
event, kCGKeyboardEventKeycode);
// Swap 'a' (keycode=0) and 'z' (keycode=6).
if (keycode == (CGKeyCode)0)
keycode = (CGKeyCode)6;
else if (keycode == (CGKeyCode)6)
keycode = (CGKeyCode)0;
// Set the modified keycode field in the event.
CGEventSetIntegerValueField(
event, kCGKeyboardEventKeycode, (int64_t)keycode);
// We must return the event for it to be useful.
return event;
}
int
main(void)
{
CFMachPortRef eventTap;
CGEventMask eventMask;
CFRunLoopSourceRef runLoopSource;
// Create an event tap. We are interested in key presses.
eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0,
eventMask, myCGEventCallback, NULL);
if (!eventTap) {
fprintf(stderr, "failed to create event tap\n");
exit(1);
}
// Create a run loop source.
runLoopSource = CFMachPortCreateRunLoopSource(
kCFAllocatorDefault, eventTap, 0);
// Add to the current run loop.
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
kCFRunLoopCommonModes);
// Enable the event tap.
CGEventTapEnable(eventTap, true);
// Set it all running.
CFRunLoopRun();
// In a real program, one would have arranged for cleaning up.
exit(0);
}
The downside to this is that you cannot sandbox or ship an application that uses ⌘⇥ on the App Store. Not only should it be obvious why Event Taps are not allowed in those environments (they give you the ability to terminate—and even mutate—events), but the functionality Dock provides on ⌘⇥ is pretty darn useful and can't be remapped to a different keyboard shortcut, so even Witch and Switch avoid it using it by default.

Resources