• Welcome to Valhalla Legends Archive.
 
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - tA-Kane

#1
I'm working on a project which needs to schedule functions to be executed in a specific thread(s) (possibly in another process as well). The specific reasons why are various.

Assume -

  • The thread in which the functions are to be executed knows about the functions and is expecting them
  • The functions are to be executed in FIFO order - that is, first come/first serve
  • The functions do not have the same types of parameters, nay even the same number of parameters
  • Obviously due to the function being called in a different thread, the parameters are not currently stored on the stack. As such, the called function assumes ownership of the parameters and will deallocate them as necessary.
  • Return values may be ignored.
Requirements -

  • Memory use is of little concern (don't waste it obviously)
  • CPU use needs to be tight

At first, I was needing to schedule less than a dozen or so functions. There was simply a container with an integer-type function identifier and a method of storing the function parameters (byte array, linked list... it didn't matter at first). We used a switch statement to identify which function to execute, and each case also assumes the number of parameters have been stored.

As the project progressed, the number of functions to be scheduled has grown by several dozen, to the current count of about 110. While that in and of itself wasn't a problem, keeping the enumeration for which function belonged to which case did become a problem to some of our newer guys. Additionally, as the project progressed, it became a concern that the code size for something so simple was increasing a great deal as the number of functions and parameters was increasing.

Unfortunately, none of the other programmers on the project could come up with a better solution.


After some thought, I a prototypeless function pointer occurred to me:

typedef void* (__cdecl FUNCPTR)(...);


This does solve the issue of the enumeration growing, as you'd simply call the passed function pointer rather than doing a switch. Ironically, this should also save a little bit of CPU, although it's probably negligible.

It does, however, present a unique situation. The different functions to be pointed to have different numbers of parameters which cannot be identified using a prototypeless function pointer like this one. As far as I am aware, while C/C++ does provide a method of manually pushing any number of parameters onto this function, it does not provide the means to programmatically determine the number of parameters a function has or their boundaries (you can't use a loop to push the parameters). Due to this, it would re-introduce the switch statement to select the number of parameters and call the function as appropriate with that number of parameters.

As such, an Asm hack seemed required. Portability issues are a non-concern, so I proceeded.

Here's what I've come up with. The other programmers on the project have no experience with assembly (and very little experience with functions prototyped with (...)), which makes them unable to check my work. As such, what do you all think of this code? Are there any issues you can see which I may have not foreseen? Anything I may have missed?

I have a static byte array in carrier to hold the parameters simply because I don't want to make two allocations for the test -- one for the carrier structure and another for the parameters. This can obviously result in a buffer overflow of which I am aware. I am also aware it can result in large amounts of memory waste when pointing to functions with few or no parameters when there's dozens of entries in the schedule queue. Assuming no drastic problems with this code, both issues will be reviewed.

Things I will need to do is move carrier to a struct (I don't even remember why I made it a union) which includes the paramsize rather than passing paramsize alongside carrier. Additionally, carrier may eventually be passed to callit() as a pointer rather than inline parameter.

Sample test code below --

typedef void* (__cdecl FUNCPTR)(...);

union carrier {
FUNCPTR *funcptr;
char va_test[512];
};
void __cdecl callit(int size, carrier omg);

int __cdecl something(char *buf, int a, int b, int c, int d, int e, int f) {
sprintf(buf, "a = %.x\nb = %.x\nc = %.x\nd = %.x\ne = %.x\nf = %.x\nwtf=%.x\n", a, b, c, d, e, f, a ^ b ^ c ^ d ^ e ^ f);
printf("%s", buf);
return a ^ b ^ c ^ d ^ e ^ f;
}

__declspec(naked) void __cdecl callit(int paramsize, carrier omg) {
__asm {
push ebp;
mov ebp, esp;
push esi;

mov ecx, paramsize;
lea esi, omg;
add esi, SIZE omg.funcptr; // skip the function ptr
shr ecx, 2; // modulo 4 ... this assumes int is (and thus params are in a multiple of) 32-bit
jz _asmparamspushed;

// TODO: look into using repeat opcodes
_asmpushparams:
push [esi];
add esi, 4;
dec ecx;
jnz _asmpushparams;

_asmparamspushed:
call omg.funcptr;

lea esp, [ebp-4];
pop esi;
pop ebp;
retn;
}
}

int _tmain(int argc, _TCHAR* argv[])
{
char buf[256];
carrier omg;
int a, b, c, d, e, f, r;
a = 0x12345678;
b = 0x87654321;
c = 0x12873465;
d = 0x13572468;
e = 0x24687531;
f = 0x18273645;
r = 0;

omg.funcptr = (FUNCPTR *)something;
va_list list, list2;

va_start(list2, omg.funcptr);
va_start(list, omg.funcptr);
va_arg(list, int) = f;
va_arg(list, int) = d;
va_arg(list, int) = e;
va_arg(list, int) = c;
va_arg(list, int) = b;
va_arg(list, int) = a;
va_arg(list, char *) = buf;
callit((int)(list - list2), omg);
printf("--- double check ---\n");
printf("%s", buf);

// let the test display to the console before exiting
gets_s(buf, sizeof(buf));
return 0;
}


[Kp edit: deleted long comment that broke table layout.]
#2
I suppose this could go in Advanced Programming? But I feel it leans more towards general C++ knowledge. :-\

I'm currently using an abstract, template<class T> class List, which allows me to add/remove structures (of type T) from a single doubly-linked list by adding two variables to the structure, T::Next and T::Previous. However, the downside to this is that it prevents the structure from being added to multiple linked lists. I cannot, for example, have one structure's instance (assume it has someone's name) in a list of employees and in a second list of clients. An employee could not be a client for the company s/he works for, and vice versa.

Would it be possible (and if so, how?) to tell the List class to use a different set of variable names (eg, tell it to use T->NextEmployee and T->NextClient)?

An obvious solution that I've thought of (but it's good to know other options, right?) would be to create another struct (maybe struct ListLinker), which contains the link pointers, and then simply have an array of that struct. Then, tell the List class which array index to use when adding/removing/etc. But there's also a catch to that: if the arrays are used extensively (which, in the future, they could), it could get to be a royal pain in the ass to keep track of which List "owns" which index, not to mention that it could waste a fair bit of memory if the array is statically allocated within T (since there are peaks of tens of thousands of instances of various T objects at runtime, it would really add up).

I suppose another solution could be to use some sort of database (such as SQL)... but I don't particularly like the overhead of that just for the ability to use multiple linked lists. ;)
#3
Let's say I've passed my program a directory that it needs to search all files and subdirectories for anything that matches a specific filename. It needs to be POSIX-compliant.

After about two hours of searching the 'net using google, I've come up with little as far as results. The best I can come up with is that fopen() will fail and set errno to EISDIR, if you do not try to open a directory with write access. With that in mind, how would I get the names of all entities in a directory? Or is there another way to do this, which I am simply too blind to see?

I did find this nice little function, but it appears (according to the read) to be only for BSD.

I would like it to be as easy as calling FindFirstFile/FindNextFile/FindClose using the WinAPI, but again, sadly that's not POSIX compliant.  :(

Any help would be appreciated!
#4
Computer Support Issues / Computer troubles...
January 05, 2006, 07:28 AM
Yesterday evening after a short nap, I awoke to find that my computer had apparently frozen. I shut it off and turned it back on, but the screens never activated. I unplugged my extra hard drives, thinking that one of them might have failed, but that did not help. I then proceeded to take out all of my add-in cards except for my graphics card, but that also did not help. Before I turn it in for warranty (eg, processor/memory/motherboard went bad -- glad I got the extended warranty, as the manufacturer's warranty ran out two weeks ago), is there anything I can do to try to get it to work again?
#5
Suppose I write a program which needs to be able to check itself for any unauthorized modifications made to it (whether in the executable's file or added after it's been launched). With the obvious problems aside (self-modifying code, storing data within executable space, etc), I'll need to be able to get the program to find the boundaries of its own executable memory space and CRC check it. Correct me if I'm wrong, but any modifications to the executable file would *most likely* also show up in the program's executable code (and if not, then there are other safeguards against data section tampering), would they not?

So with that in mind, how might I go about getting (eg, what API calls) the program's executable code memory boundaries? Are there any things to consider when accessing such memory without actually executing it? This is, of course, assuming that the CRC code will be within those boundaries and will of course include itself in the checksumming process.

Another thing to think about is when using this in connection with a server verification scheme ... it is possible for a modified executable to always send the correct checksum by either modifying the code the sends the checksum to the server, modifying the checksum algorithm to simply immediately return the correct value, or etc. What would be a feasible method of adding some randomness to the code which would make the checksum almost never be a static value? Perhaps have the server send a random value or maybe some code to inject at various places within the CRC algorithm, which could alter the result but yet will not make the algorithm unstable?
#6
General Discussion / Awesome keyboard
July 24, 2005, 04:33 AM
#7
I'm currently disassembling an anti-hack program that is protected using (I assume) SVKP. While I believe I am making progress, I do believe I've hit a small stump.

First, let me explain what I've noticed this thing doing so far.

At the program launch, it decodes a few strings containing pathnames to known debugger files and attempts to open those files. If none were successfully opened, it proceeds to the next step.

From here on out, a lot of jumps are used to skip junk bytes in the code, and numerous (though easily identifiable) useless jumps which are assumably throwing a debugger or disassembler off.

What it does next is copy some what I thought was junk data to the stack. Then to my astonishment, it jumped to the stack. With that in mind, it's obviously trying to throw disassemblers off there ... since the instructions are embedded into a number of mov instructions (and in fact are actually decoded using various xors before being pushed to the stack), a disassembler would not be able to disassemble those instructions without a *lot* of help.

In any case, what that appears to be doing is decrypting a small amount of code inside the data section, and then jumps there. That also decrypts a larger amount of code in the data section and then jumps to it, which also decrypts more code. The sixth or seventh time doing this, it references the origional code.

I'm not totally sure what to do, and I was wondering (for those of you whom have disassembly knowledge). I have a vague idea, but I don't think it'd be good in terms of time taken.

Thoughts?
#8
General Discussion / Bandwidth vs Latency
February 22, 2005, 05:58 AM
I was playing a game yesterday when someone asked me a question which I have answered countless times for various people. It has prompted me to write a short document explaining the matter.

Would anyone care to comment?

http://linkware.clan-mac.com/kanebot/misc/bandwidthvslatency.txt
#9
I have a question regarding the BinaryChat plugin API, directed at anyone who's knowledgable in that area. I have not found any documentation on the API, except the few comments that's written in the API's headers.

My plugin needs to find out the home channel of the connection, and I'm goign to assume that I need to use API.QueryConfigurationSetting(), however, I am oblivious as to what I need to pass for the Profile parameter, and it seems that the API call returns FALSE and Buffer is unmodified without valid data passed to it (eg, I can't just pass NULL).

Could someone help me please?
#10
General Programming / Weird memory-associated error
February 07, 2005, 05:44 PM
I seem to be having trouble with one of the most fundamental operators of C++: the new and delete operators. Hmmm...

int i;
char *saved;
bool success;

// some initialization and sanity checks here
...

// msg->line is a char array
i = strlen(msg->line);
if (i <= 0)
saved = NULL;
else
{
saved = new char[i];
if (saved)
strcpy(saved, msg->line);
}

// middle code that modifies msg->line
...

// now check to see if i want to log the msg, if i do, then restore msg->line and send to logging function
if (!success)
{
if (!saved)
irc_dbg(__FILE__, __LINE__, "failure saving message, hopefully no changes were made");
else
strcpy(msg->line, saved);
irc_log(irc, msg);
if (saved)
delete[] saved;
}
Now, this code looks fine to me, but when I execute it, I get an error...
QuoteDebug Error!

Program C:\Program Files\SphtBotv3\SphtBotv3.exe

DAMAGE: after Normal block (#63) at 0x020D1C40.


(Press Retry to debug the application)

I've traced it down to the delete[] call, but I don't think I'm understanding why that's failing...?

I've also tried removing the code between the allocation and the deallocation, thinking maybe I fucked up somewhere and was modifying saved, but no... even with no middle code, it still fails.

Could someone point me in the right direction, please?
#11
General Programming / DLLs & messages for them
January 25, 2005, 03:08 AM
I'm trying to write a DLL (BCP actually, but that's not really important) which creates and uses sockets. I don't want it to hog the owning executable's processing time, so I of course would rather use asynchronous calls. But from the looks, they require a window to be passed to them in order to receive events such as data available.

I would rather not create a window (it's a DLL, it shouldn't need an interface!), so how might I go around this?
#12
General Discussion / broadband modem/router/gateway
January 23, 2005, 04:41 PM
I have a DSL connection that IMO is really eww. I need to run VPN for work, it says it supports VPN, but anytime I try to get my work's software to connect through it, it fails. I think it's the gateway that I'm connected with, a 2Wire HomePortal 1000SW. I bought a router that my work says will work with their VPN, but I'm not totally sure that it's all about that. I asked work about it, but they say they're not going to assist me in setting it up, they only know that the router works on their own home systems (wtf you punk-ass dorks  :P)

Will this work behind NAT? I don't think it will, I think it needs to have direct access to the internet, but I don't think my DSL gateway will allow that. Back in California, I had a different setup; the DSL modem back there didn't do jack shit... it simply acted like a DSL-ethernet bridge, and anything connected to the modem was directly connected to the internet... to get something behind NAT, I had to install a router and put things behind that.

Kind of a *real* pain in the ass. I wish my DSL company would have sent me a *real* man's dsl modem, not a dsl gateway for the fucking newbies.  :(

Alternately, I think I could get this set up correctly if I could get another DSL modem like the one in California, but I don't remember the brand/model that I had back in there...  :(
#13
Battle.net Bot Development / BNLS "authorizer"
January 10, 2005, 08:52 AM
Some bots (in particular, the one I'm using ... *cough*Spht*cough*) seem to not like it when BNLS returns 0x01 for the status to BNLS_AUTHORIZEPROOF reply (meaning that the bot's ID or password was invalid). Whether it's intentional (disable old versions or whatever) or not (didn't allow for nonzero statuscodes, accidental BNLS password change, etc), this can be annoying. If the bot you're using allows you to change the BNLS server to 127.0.0.1, then you could try this. It simply passes data between the bot and the real BNLS server, except that when the BNLS_AUTHORIZEPROOF reply is sent from the server, the status code always gets changed to 0x00 (bot is authorized), which makes the bot think it's allowed to move on.

BNLS seems to be down at the moment, so I'm not able to test it myself (eww...), so hopefully someone else will be able to, because I'm about to fall asleep.

By the way, this is my first Win32 app.

http://linkware.clan-mac.com/kanebot/misc/bnls_authorizer.zip
#14
General Discussion / printing voices
December 31, 2004, 12:39 PM
i got a new printer for xmas, and only got around to setting it up this morning...

is there any way to stop the printer driver from saying "printing started" and "printing finished" when such an even occurs? it's really quite annoying!
#15
General Discussion / Awesome computer ... or not?
December 18, 2004, 01:11 AM
- Pentium 4 550 @ 3.4GHz
- 800MHz FSB
- 1MB L2 Cache
- 1GB Dual Channel PC3200 DDR RAM, max of 4GB
- XP Pro
- 250GB SATA w/ 8MB Cache @ 7200 RPM
- 128MB GeForce 5300FX PCI Express
- Intel High-def 7.1 audio
- 16x Dual-Layer DVD+-RW
- 16x DVD+-ROM

$1299 U.S., $999 after rebates

I think it's a sweet price, but what do all ya'll think? Co-workers said it's a good deal too, being that it's under $1100. I'll be getting it in less than 12 hours ...   ;D 8)
#16
I've been thinking a bit more about the problem that I've had for the past two years or so; and that's that at seemingly random times when my bot is connecting with WarCraft 3, it gets itself into a login-then-disconnected state, where it's able to login to the server just to be immediately disconnected by the server... I call that a "silent violation" since you don't really know what you violated.

I recently disabled my icons support for a different reason, but it seems that I'm not getting this problem anymore.

So I've looked into this a little more, and it seems that I was neglecting to use the BnFTP version 2 when downloading the icons file that Battle.net told my bot to download; so I would end up sending the BnFTP header using WAR3 as the game, get disconnected by the server, and then revert back the the file in my cache which was downloaded by my bot when connecting on a different product (usually STAR or W2BN).

So, it seems that that is the problem. But I wonder; is it really? I've yet to look into the BnFTP v2 stuff (I hear it has some stuff from 0x51, though)... but if what I'm saying is indeed true, where's some information on BnFTP v2? I did a brief search and found this mostly unhelpful topic: http://forum.valhallalegends.com/phpbbs/index.php?topic=6354.0

Unfrotunately, I do not have a packetlog of a valid BnFTP v2 connection (and am not currently in a position to obtain one), otherwise I would try to guesstimate what everything is myself.
#17
Battle.net Bot Development / BnetDocs "ToDo"
September 23, 2004, 02:03 PM
As you may or may not know, BnetDocs has been updated quite a bit recently. Certain people who have made a number of contributions have been given permission to edit certain things, likely so that Arta doesn't get bogged down with questions or requests...  :)

I've also been redoing my own bot a fair bit, and checking some things against BnetDocs, testing a few things, and updating some things (only three things have I updated at this point). I've also come up with a list of questions for myself.

I figured that with the amount of time that I really don't have to try to find the answers (most of them are simple, but my bot is not at a point for me to be able to answer them at this time), so I figured I might start a thread here for people to post questions about BnetDocs and answers to them. If you're feeling really bored, you can go through BnetDocs and find things that might be a little vague or perhaps not even fully documented, and either ask questions or provide an answer. Then, I'm sure some of the recently-made editors of BnetDocs would be happy to update the information to be correct.

This could serve the dual-purpose of providing a kind of version or update history of BnetDocs. Those of you who've already implemented your bot according to one (wrong or incomplete) statement on BnetDocs can read here and update your bot accordingly.

I'll get ya'll started with some things to do that I I don't have the time to find the answers for:

-  Get valid results for S->0x78
-  Get valid results for S->0x7A
-  Verify Status is a DWORD for S->0x74
-  Get valid results for S->0x74
-  Get valid Type and Status values for S->0x67
-  Verify Result is a DWORD for S->0x71
-  "Commonize" naming for Result / Status byte (DWORD in some packets, apparently?) for clan packets (I would likely use "Result" as the name)


Here's the three items I've already done:
September 13, 2004 12:10 AM
-  Added packet format for S->0x77
-  Moved valid results for S->0x77's Format field to Description field

September 12, 2004 11:00 PM
-  Added 0x07 (Not Authorized) to valid result for S->0x73

Hopefully this works out to an advantage... :)
#18
When a clan gets disbanded, does 0x73 get sent to every member online, or only the leader that send the disband request?

I would think it gets sent to every member, but I just want to make sure since I have no experience with clans or clan packets.
#19
As some of you know, my dad works at TI. He's a winner for some contest at his building for winning one of ANY currently-manufactured TI calculator. So... yeah...

Which one would you pick?

"*Current TI Calculators include: TI-10, TI-15, TI-34 II, TI-30Xa, TI-30X IIS, TI-30X IIB, TI-36X, TI-73 Explorer, TI-83 Plus, TI-84 Plus, TI-84 Plus Silver Edition, TI-86, TI-89 Titanium, Voyage 200. Or you may choose a TI Keyboard or CBR motion sensor."

Edit: You can visit http://education.ti.com to learn more about their different caluclators.
#20
i don't have the code with me at the moment, but yesterday i had a weird problem with a standard file stream, in that I would read 4 bytes into a long, record the position in the file that it's currently at, move to somewhere else based on that long, and then reset to the position where it was (so it SHOULD end back up just after the 4 bytes)...

but the problem was that for some weird reason, it incremented the position by 16 bytes, even though it read only 4 bytes

im about to leave for work in 20 minutes, and am not on my mac... but when i get back from work, i'll post the code


anyone have any ideas why it's doing this?