static int uiToggleControls(Ihandle *ih, int state) { Ihandle *controls = (Ihandle*)IupGetAttribute(ih, CONTROLS_HANDLE); short *target = (short*)IupGetAttribute(ih, SYNCED_VALUE); int controlsActive = IupGetInt(controls, "ACTIVE"); if (controlsActive && !state) { IupSetAttribute(controls, "ACTIVE", "NO"); InterlockedExchange16(target, I2S(state)); } else if (!controlsActive && state) { IupSetAttribute(controls, "ACTIVE", "YES"); InterlockedExchange16(target, I2S(state)); } return IUP_DEFAULT; }
// naive fixed number of (short) * 0.01 int uiSyncFixed(Ihandle *ih) { short *fixedPointer = (short*)IupGetAttribute(ih, SYNCED_VALUE); const float maxFixedValue = IupGetFloat(ih, FIXED_MAX); const float minFixedValue = IupGetFloat(ih, FIXED_MIN); float value = IupGetFloat(ih, "VALUE"); float newValue = value; short fixValue; char valueBuf[8]; if (newValue > maxFixedValue) { newValue = maxFixedValue; } else if (newValue < minFixedValue) { newValue = minFixedValue; } if (newValue != value && value != 0) { sprintf(valueBuf, "%.2f", newValue); IupStoreAttribute(ih, "VALUE", valueBuf); // put caret at end to enable editing while normalizing IupStoreAttribute(ih, "CARET", "10"); } // sync back fixValue = newValue / FIXED_EPSILON; InterlockedExchange16(fixedPointer, fixValue); return IUP_DEFAULT; }
// shared callbacks int uiSyncChance(Ihandle *ih) { char valueBuf[8]; float value = IupGetFloat(ih, "VALUE"), newValue = value; short *chancePtr = (short*)IupGetAttribute(ih, SYNCED_VALUE); if (newValue > 100.0f) { newValue = 100.0f; } else if (newValue < 0) { newValue = 0.0f; } if (newValue != value) { // equality compare is fine since newValue is a copy of value sprintf(valueBuf, "%.1f", newValue); IupStoreAttribute(ih, "VALUE", valueBuf); // put caret at end to enable editing while normalizing IupStoreAttribute(ih, "CARET", "10"); } // and sync chance value InterlockedExchange16(chancePtr, (short)(newValue * 100)); return IUP_DEFAULT; }
int uiSyncInteger(Ihandle *ih) { short *integerPointer = (short*)IupGetAttribute(ih, SYNCED_VALUE); const int maxValue = IupGetInt(ih, INTEGER_MAX); const int minValue = IupGetInt(ih, INTEGER_MIN); // normalize input into [min, max] int value = IupGetInt(ih, "VALUE"), newValue = value; char valueBuf[8]; if (newValue > maxValue) { newValue = maxValue; } else if (newValue < minValue) { newValue = minValue; } // test for 0 as for empty input if (newValue != value && value != 0) { sprintf(valueBuf, "%d", newValue); IupStoreAttribute(ih, "VALUE", valueBuf); // put caret at end to enable editing while normalizing IupStoreAttribute(ih, "CARET", "10"); } // sync back InterlockedExchange16(integerPointer, (short)newValue); return IUP_DEFAULT; }
int uiSyncToggle(Ihandle *ih, int state) { short *togglePtr = (short*)IupGetAttribute(ih, SYNCED_VALUE); InterlockedExchange16(togglePtr, I2S(state)); return IUP_DEFAULT; }
static int sendAllListPackets() { // send packet from tail to head and remove sent ones int sendCount = 0; UINT sendLen; PacketNode *pnode; #ifdef _DEBUG // check the list is good // might go into dead loop but it's better for debugging PacketNode *p = head; do { p = p->next; } while (p->next); assert(p == tail); #endif while (!isListEmpty()) { pnode = popNode(tail->prev); sendLen = 0; assert(pnode != head); // FIXME inbound injection on any kind of packet is failing with a very high percentage // need to contact windivert auther and wait for next release if (!WinDivertSend(divertHandle, pnode->packet, pnode->packetLen, &(pnode->addr), &sendLen)) { PWINDIVERT_ICMPHDR icmp_header; PWINDIVERT_ICMPV6HDR icmpv6_header; PWINDIVERT_IPHDR ip_header; PWINDIVERT_IPV6HDR ipv6_header; LOG("Failed to send a packet. (%lu)", GetLastError()); dumpPacket(pnode->packet, pnode->packetLen, &(pnode->addr)); // as noted in windivert help, reinject inbound icmp packets some times would fail // workaround this by resend them as outbound // TODO not sure is this even working as can't find a way to test // need to document about this WinDivertHelperParsePacket(pnode->packet, pnode->packetLen, &ip_header, &ipv6_header, &icmp_header, &icmpv6_header, NULL, NULL, NULL, NULL); if ((icmp_header || icmpv6_header) && IS_INBOUND(pnode->addr.Direction)) { BOOL resent; pnode->addr.Direction = WINDIVERT_DIRECTION_OUTBOUND; if (ip_header) { UINT32 tmp = ip_header->SrcAddr; ip_header->SrcAddr = ip_header->DstAddr; ip_header->DstAddr = tmp; } else if (ipv6_header) { UINT32 tmpArr[4]; memcpy(tmpArr, ipv6_header->SrcAddr, sizeof(tmpArr)); memcpy(ipv6_header->SrcAddr, ipv6_header->DstAddr, sizeof(tmpArr)); memcpy(ipv6_header->DstAddr, tmpArr, sizeof(tmpArr)); } resent = WinDivertSend(divertHandle, pnode->packet, pnode->packetLen, &(pnode->addr), &sendLen); LOG("Resend failed inbound ICMP packets as outbound: %s", resent ? "SUCCESS" : "FAIL"); InterlockedExchange16(&sendState, SEND_STATUS_SEND); } else { InterlockedExchange16(&sendState, SEND_STATUS_FAIL); } } else { if (sendLen < pnode->packetLen) { // TODO don't know how this can happen, or it needs to be resent like good old UDP packet LOG("Internal Error: DivertSend truncated send packet."); InterlockedExchange16(&sendState, SEND_STATUS_FAIL); } else { InterlockedExchange16(&sendState, SEND_STATUS_SEND); } } freeNode(pnode); ++sendCount; } assert(isListEmpty()); // all packets should be sent by now return sendCount; }
static void resetCloseDown(PacketNode *head, PacketNode *tail) { UNREFERENCED_PARAMETER(head); UNREFERENCED_PARAMETER(tail); LOG("reset disabled"); InterlockedExchange16(&setNextCount, 0); }
static void resetStartup() { LOG("reset enabled"); InterlockedExchange16(&setNextCount, 0); }