Core Function DLLStructCreate
DLLStructCreate( <def string> )
Contents |
Description
Creates a C/C++ style structure to be used with DLLCall
Parameters
def string
A string representing the structure to create (See Remarks).
Return Value
Success - Returns the DLLStruct.
Failure - Returns null and most likely throws exception.
Remarks
To delete a DLLStruct you must unset it example:
unset( $dllStruct );
Note - If you do not unset the DLLStruct and instead just change the value of the variable then the garbage collector will deal with the DLLStruct *evenutally* but that could be today, tomorrow you never know so always unset() the struct when your finished with it.
DEFS
Each data type must be separated by a semi-colon ';'.
Create arrays by adding '[size]' after the data type.
DllStructCreate("int;char[128]").
An elementname can be added similar to a C-style declaration DllStructCreate("int n;char buffer[128]").
If the definition begins with "union " you will create the struct the same as a C union type example: $a = DllStructCreate("union int a;float b");
def string settings
[TYPE] [WHAT IT RETURNS WITH DLLSTRUCTGETDATA] [WHAT IS IT IN C++] ubyte unsigned 8 bit integer unsigned char byte signed 8 bit integer char char a single ASCII character char wchar a single UNICODE character wchar short signed 16 bit integer short int16 signed 16 bit integer short int signed 32 bit integer int int32 signed 32 bit integer int int64 signed 64 bit integer __int64 long signed 64 bit integer __int64 ushort signed unsigned 16 bit integer unsigned short uint16 signed unsigned 16 bit integer unsigned short uint signed unsigned 32 bit integer unsigned int uint32 signed unsigned 32 bit integer unsigned int uint64 signed unsigned 64 bit integer unsigned __int64 ulong signed unsigned 64 bit integer unsigned __int64 float signed 32 bit floating point float double signed 64 bit floating point double char* a pointer to an ASCII char array (string) char* wchar* a pointer to an UNICODE char array (string) wchar* ptr a pointer void* uptr a unsigned pointer unsigned void* Note - There is no *string* type instead; You must create an array of chars example "char mystring[500]" then you can use it like a string. Or if you wish to use UNICODE its "wchar mystring[500]" Warning - Remember to free() etc when your working with allocated memory and pointers.
Example
Example of placing DLLStructs inside DLLStructs
// Define a POINT struc to include in our main struct DLLStructCreateDef("POINT", "int x;int y"); // Create the struct my $Struct = DLLStructCreate( // Of course @"" makes producing the struct almost identical to C/C++ @" int i; char* name; char* pass; char* id[3]; POINT loc; POINT lastLoc; int j; "); // Write the data DLLStructSetData($Struct, "i", 100); DLLStructSetData($Struct, "j", 200); DLLStructSetData($Struct, "name", "Testy"); DLLStructSetData($Struct, "pass", "Another Testy"); DLLStructSetData($Struct, "id", "This is ID 0", 0); DLLStructSetData($Struct, "id", "This is ID 1", 1); DLLStructSetData($Struct, "id", "This is ID 2", 2); DLLStructSetData($Struct, "loc->x", 50); DLLStructSetData($Struct, "loc->y", 70); DLLStructSetData($Struct, "lastLoc->x", 11); DLLStructSetData($Struct, "lastLoc->y", 22); // Print the data println( "I = " . DLLStructGetData($Struct, "i") ); println( "J = " . DLLStructGetData($Struct, "j") ); println( "Name = " . DLLStructGetData($Struct, "name") ); println( "Pass = " . DLLStructGetData($Struct, "pass") ); println( "ID 0 = " . DLLStructGetData($Struct, "id", 0) ); println( "ID 1 = " . DLLStructGetData($Struct, "id", 1) ); println( "ID 2 = " . DLLStructGetData($Struct, "id", 2) ); println( "Loc->x = " . DLLStructGetData($Struct, "loc->x") ); println( "Loc->y = " . DLLStructGetData($Struct, "loc->y") ); println( "lastLoc->x = " . DLLStructGetData($Struct, "lastLoc->x") ); println( "lastLoc->y = " . DLLStructGetData($Struct, "lastLoc->y") );
Same as above but with more structs inside structs
// Define a SIZE struc to include in the POINT struct DLLStructCreateDef("SIZE", "int width;int height"); // Define a POINT struc to include in our main struct DLLStructCreateDef("POINT", "int x;int y;SIZE s"); // Create the struct my $Struct = DLLStructCreate( // Of course @"" makes producing the struct almost identical to C/C++ @" int i; char* name; char* pass; char* id[3]; POINT loc; POINT lastLoc; int j; "); // Write the data DLLStructSetData($Struct, "i", 100); DLLStructSetData($Struct, "j", 200); DLLStructSetData($Struct, "name", "Testy"); DLLStructSetData($Struct, "pass", "Another Testy"); DLLStructSetData($Struct, "id", "This is ID 0", 0); DLLStructSetData($Struct, "id", "This is ID 1", 1); DLLStructSetData($Struct, "id", "This is ID 2", 2); DLLStructSetData($Struct, "loc->x", 50); DLLStructSetData($Struct, "loc->y", 70); DLLStructSetData($Struct, "loc->s->width", 800); DLLStructSetData($Struct, "loc->s->height", 600); DLLStructSetData($Struct, "lastLoc->x", 11); DLLStructSetData($Struct, "lastLoc->y", 22); DLLStructSetData($Struct, "lastLoc->s->width", 640); DLLStructSetData($Struct, "lastLoc->s->height", 480); // Print the data println( "I = " . DLLStructGetData($Struct, "i") ); println( "J = " . DLLStructGetData($Struct, "j") ); println( "Name = " . DLLStructGetData($Struct, "name") ); println( "Pass = " . DLLStructGetData($Struct, "pass") ); println( "ID 0 = " . DLLStructGetData($Struct, "id", 0) ); println( "ID 1 = " . DLLStructGetData($Struct, "id", 1) ); println( "ID 2 = " . DLLStructGetData($Struct, "id", 2) ); println( "Loc->x = " . DLLStructGetData($Struct, "loc->x") ); println( "Loc->y = " . DLLStructGetData($Struct, "loc->y") ); println( "Loc->s->width = " . DLLStructGetData($Struct, "Loc->s->width") ); println( "Loc->s->height = " . DLLStructGetData($Struct, "Loc->s->height") ); println( "lastLoc->x = " . DLLStructGetData($Struct, "lastLoc->x") ); println( "lastLoc->y = " . DLLStructGetData($Struct, "lastLoc->y") ); println( "lastLoc->s->width = " . DLLStructGetData($Struct, "lastLoc->s->width") ); println( "lastLoc->s->height = " . DLLStructGetData($Struct, "lastLoc->s->height") );
Example of placing DLLStructs inside DLLStructs inside DLLStructs and so on
// Create a POINT struct DLLStructCreateDef("POINT", "int x;int y"); // Create a RECT struct that contains POINT structs DLLStructCreateDef("RECT", "POINT pos;POINT size"); // Create the main struct that will incluyde a RECT struct my $Struct = DLLStructCreate( // Of course @"" makes producing the struct almost identical to C/C++ @" int i; char* name; char* pass; char* id[3]; RECT r; int j; "); // Write the data DLLStructSetData($Struct, "i", 100); DLLStructSetData($Struct, "j", 200); DLLStructSetData($Struct, "name", "Testy"); DLLStructSetData($Struct, "pass", "Another Testy"); DLLStructSetData($Struct, "id", "This is ID 0", 0); DLLStructSetData($Struct, "id", "This is ID 1", 1); DLLStructSetData($Struct, "id", "This is ID 2", 2); DLLStructSetData($Struct, "r->pos->x", 50); DLLStructSetData($Struct, "r->pos->y", 70); DLLStructSetData($Struct, "r->size->x", 11); DLLStructSetData($Struct, "r->size->y", 22); // Print the data println( "I = " . DLLStructGetData($Struct, "i") ); println( "J = " . DLLStructGetData($Struct, "j") ); println( "Name = " . DLLStructGetData($Struct, "name") ); println( "Pass = " . DLLStructGetData($Struct, "pass") ); println( "ID 0 = " . DLLStructGetData($Struct, "id", 0) ); println( "ID 1 = " . DLLStructGetData($Struct, "id", 1) ); println( "ID 2 = " . DLLStructGetData($Struct, "id", 2) ); println( "r->pos->x = " . DLLStructGetData($Struct, "r->pos->x") ); println( "r->pos->y = " . DLLStructGetData($Struct, "r->pos->y") ); println( "r->size->x = " . DLLStructGetData($Struct, "r->size->x") ); println( "r->size->y = " . DLLStructGetData($Struct, "r->size->y") );
An example on using the struct with char* and even char* [] array
// Create the struct my $Struct = DLLStructCreate( // Of course @"" makes producing the struct almost identical to C/C++ @" int i; char* name; char* pass; char* id[3]; int j; "); // Write the data DLLStructSetData($Struct, "i", 100); DLLStructSetData($Struct, "j", 200); DLLStructSetData($Struct, "name", "Testy"); DLLStructSetData($Struct, "pass", "Another Testy"); DLLStructSetData($Struct, "id", "This is ID 0", 0); DLLStructSetData($Struct, "id", "This is ID 1", 1); DLLStructSetData($Struct, "id", "This is ID 2", 2); // Print the data println( "I = " . DLLStructGetData($Struct, "i") ); println( "J = " . DLLStructGetData($Struct, "j") ); println( "Name = " . DLLStructGetData($Struct, "name") ); println( "Pass = " . DLLStructGetData($Struct, "pass") ); println( "ID 0 = " . DLLStructGetData($Struct, "id", 0) ); println( "ID 1 = " . DLLStructGetData($Struct, "id", 1) ); println( "ID 2 = " . DLLStructGetData($Struct, "id", 2) );
Another example
/*========================================================= Create the struct struct { int var1; unsigned char var2; unsigned int var3; char var4[128]; } =========================================================*/ $str = "int var1;ubyte var2;uint var3;char var4[128]"; $a = DllStructCreate($str); if ( !$a ) { MsgBox("Error in DllStructCreate"); exit(); } /*========================================================= Set data in the struct struct.var1 = -1; struct.var2 = 255; struct.var3 = 777; strcpy(struct.var4,"Hello"); struct.var4[0] = 'h'; =========================================================*/ DllStructSetData($a,"var1",-1); DllStructSetData($a,"var2",255); DllStructSetData($a,"var3",777); DllStructSetData($a,"var4","Hello"); DllStructSetData($a,"var4","G",0); /*========================================================= Display info in the struct ;=========================================================*/ MsgBox("Struct Size: " . DllStructGetSize($a) . @CRLF . "Struct pointer: " . DllStructGetPtr($a) . @CRLF . "Data:" . @CRLF . DllStructGetData($a,"var1") . @CRLF . DllStructGetData($a,"var2") . @CRLF . DllStructGetData($a,"var3") . @CRLF . DllStructGetData($a,"var4"), "DllStruct");
Heres an example of using DLLStruct
// Create the struct $a = DLLStructCreate("int x; int y"); // Print its info just for sake of it println( "DLLStruct info: " . $a ); // Call "GetCursorPos" API and send the struct to it using the "t" param $ret = DLLCall("User32.dll", "GetCursorPos", "Int32", "t", "Ansi", $a); if($ret) { // Get the X and Y from the struct $x = DLLStructGetData($a, "x"); $y = DLLStructGetData($a, "y"); // Print it println("X '$x' Y '$y'"); } else { println("GetCursorPos() api failed..."); }
Another DLLStruct example
// Create the struct $a = DLLStructCreate("char x[500]; char y[500]; char z[500]"); // Print its info just for sake of it println( "DLLStruct info: " . $a ); // Zero term the strings just to be sure DLLStructSetData($a, "x", "\0", 0); DLLStructSetData($a, "y", "\0", 0); DLLStructSetData($a, "z", "\0", 0); // Call a few apis DLLCall("user32.dll", "wsprintf", "", "tpii", "Ansi", DLLStructGetPtr($a, "x"), "Number is '%d' in hex '%x'", 100, 200); DLLCall("user32.dll", "wsprintf", "", "tpii", "Ansi", DLLStructGetPtr($a, "y"), "Number is '%d' in hex '%x'", 1337, 4242); DLLCall("user32.dll", "wsprintf", "", "tpp", "Ansi", DLLStructGetPtr($a, "z"), "STR '%s'", DLLStructGetData($a, "x")); // This time lets use lstrcat to append text to our strings DLLCall("kernel32.dll", "lstrcat", "", "tp", "Ansi", DLLStructGetPtr($a, "z"), " | Added to string"); DLLCall("kernel32.dll", "lstrcat", "", "tp", "Ansi", DLLStructGetPtr($a, "z"), "; Also added..."); // Print it println( DLLStructGetData($a, "x") ); println( DLLStructGetData($a, "y") ); println( DLLStructGetData($a, "z") ); println( "Length of X is: " . DLLCall("kernel32.dll", "lstrlen", "Int32", "t", "Ansi", DLLStructGetPtr($a, "x")) ); println( "Length of Y is: " . DLLCall("kernel32.dll", "lstrlen", "Int32", "t", "Ansi", DLLStructGetPtr($a, "y")) ); println( "Length of Z is: " . DLLCall("kernel32.dll", "lstrlen", "Int32", "t", "Ansi", DLLStructGetPtr($a, "z")) );
A very large DLLCall + DLLStruct example using C function sprintf :
$myString = WSPrintf('Testing "%c%c%c" %d | %u hehe %d....%s %f', 'A', 'B', 'B', 12, 131, 200, "omg", 133.77); println($myString); // Use the sprintf from msvcrt as an example for DLLCall // Havent added uint64/int64 support yet // Of course we could have just built the new string as we found params // but that wouldnt be using dll then would it? // Also this demonstrates the Eval() function to dynamically create Sputnik code [Args("true")] // Allow the @args variable to be made (we will use it) Function WSPrintf( $Format ) { $Args = array(); $Len = StrLen($Format); $EstMaxLen = $Len; $LastC = ''; $DLLParDef = ""; $DLLPars = ""; $b64Bit = false; for(my $i = 0, my $j = 1; $i < $Len; $i++) { $char = $Format[$i]; switch ($char) { case '%': { if($LastC == "\\") break; $i++; if($i >= $Len) { throw new exception("Format string is invalid"); return 0; } $char = $Format[$i]; switch ($char) { case '%': { $b64Bit = false; } break; case 'l': case 'L': { $b64Bit = true; } break; case 'c': { $EstMaxLen += 2; $DLLParDef .= "b"; $DLLPars .= ', (Char)@args[' . $j . ']'; $j++; $b64Bit = false; } break; case 'd': case 'i': case 'o': case 'p': { if($b64Bit) { $EstMaxLen += 20; $DLLParDef .= "l"; $DLLPars .= ', (Int64)@args[' . $j . ']'; } else { $EstMaxLen += 11; $DLLParDef .= "i"; $DLLPars .= ', (Int32)@args[' . $j . ']'; } $j++; $b64Bit = false; } break; case 'o': case 'u': case 'x': case 'X': { if($b64Bit) { $EstMaxLen += 20; $DLLParDef .= "L"; $DLLPars .= ', (UInt64)@args[' . $j . ']'; } else { $EstMaxLen += 11; $DLLParDef .= "I"; $DLLPars .= ', (UInt32)@args[' . $j . ']'; } $j++; $b64Bit = false; } break; case 'f': case 'g': case 'e': case 'E': { $EstMaxLen += 20; $DLLParDef .= "d"; $DLLPars .= ', (double)@args[' . $j . ']'; $j++; $b64Bit = false; } break; case 's': { $EstMaxLen += StrLen(@Args[$j] + 1); $DLLParDef .= "p"; $DLLPars .= ', (string)@args[' . $j . ']'; $j++; $b64Bit = false; } break; default: { throw new exception("Invalid specifier '$char'"); return 0; } break; } } break; } $LastC = $char; } // Create the correct size struct which will hold the newly made string // It should have been calculated to a good degree of accuracy so we // Dont really expect any buffer overflows here $Struct = DLLStructCreate("char buf[$EstMaxLen];"); // Create the DLL call string $CallString = 'DLLCall("msvcrt.dll", "sprintf", "Int32", "tp' . $DLLParDef . '", "Ansi:cdecl", $Struct, $Format' . $DLLPars . ');'; $RetVal = Eval($CallString); // Dynamically call the dll using the string as if it was physical Sputnik code if(Eval($CallString) == 0) { unset($Struct); // Cleanup the Struct return 0; } $newStr = DLLStructGetData($Struct, "buf"); unset($Struct); // Cleanup the Struct return $newStr; }
A very large DLLCall + DLLStruct example using C function sprintf :
This time we will use a cache to store the DLL imported functions in a buffer and execute it again without having to recompile it each time the function is called.
The way it will work is it will remember your param defs such as "ippi" if the defs are the same when you call the function again it will use the previously compiled and cached function instead of creating a new one.
The benefit of this is amazing speed improvement by up to 10 fold.
Global $CallArray = array(); // Store imported DLL functions // Print 10,000 items very rapidly my $Tick = TickCount(); for(my $i = 0; $i < 10000; $i++) { $var = CSPrintf("The value is '%d'\n", $i); print("Returned: $var"); } say("Final (in seconds): " . (TickCount($Tick) / 1000.0)); [Args("true")] // Allow the @args variable to be made (we will use it) Function CSPrintf( $Format ) { $Args = array(); $Len = StrLen($Format); $EstMaxLen = $Len; $LastC = ''; $DLLParDef = ""; $DLLPars = ""; $b64Bit = false; for(my $i = 0, my $j = 1; $i < $Len; $i++) { $char = $Format[$i]; switch ($char) { case '%': { if($LastC == "\\") break; $i++; if($i >= $Len) { throw new exception("Format string is invalid"); return 0; } $char = $Format[$i]; switch ($char) { case '%': $b64Bit = false; break; case 'l': case 'L': $b64Bit = true; break; case 'c': $EstMaxLen += 2; $DLLParDef .= "b"; $DLLPars .= ', (Char)@args[' . $j . ']'; $j++; $b64Bit = false; break; case 'd': case 'i': case 'o': case 'p': if($b64Bit) { $EstMaxLen += 20; $DLLParDef .= "l"; $DLLPars .= ', (Int64)@args[' . $j . ']'; } else { $EstMaxLen += 11; $DLLParDef .= "i"; $DLLPars .= ', (Int32)@args[' . $j . ']'; } $j++; $b64Bit = false; break; case 'o': case 'u': case 'x': case 'X': if($b64Bit) { $EstMaxLen += 20; $DLLParDef .= "L"; $DLLPars .= ', (UInt64)@args[' . $j . ']'; } else { $EstMaxLen += 11; $DLLParDef .= "I"; $DLLPars .= ', (UInt32)@args[' . $j . ']'; } $j++; $b64Bit = false; break; case 'f': case 'g': case 'e': case 'E': $EstMaxLen += 20; $DLLParDef .= "d"; $DLLPars .= ', (double)@args[' . $j . ']'; $j++; $b64Bit = false; break; case 's': $EstMaxLen += StrLen(@Args[$j] + 1); $DLLParDef .= "p"; $DLLPars .= ', (string)@args[' . $j . ']'; $j++; $b64Bit = false; break; default: throw new exception("Invalid specifier '$char'"); return 0; break; } } break; } $LastC = $char; } // Create a unique hash that will be the same for everything that calls this function with the same definition // but allow for unique parameters to be passed of course my $Hash = 'sprintf' . Hash('p' . $DLLParDef); if((!IsKeySet($CallArray, $Hash))) { my $RandName = "sprintf_" . RandStr(10); // Generate name for new function (must be unique) $CallArray[$Hash] = $RandName; // Insert the function name into array // Create the function by importing it form the DLL DLLImport("msvcrt.dll", "sprintf:$RandName", "Int32", "tp$DLLParDef", "Ansi:cdecl"); } // Get function name from array so we can call it my $FuncName = $CallArray[$Hash]; // Create the correct size struct which will hold the newly made string // It should have been calculated to a good degree of accuracy so we // Dont really expect any buffer overflows here $Struct = DLLStructCreate("char buf[$EstMaxLen];"); // Build a string to execute as Sputnik code $CallString = $FuncName . '($Struct, $Format' . $DLLPars . ');'; // Call it if(Eval($CallString) == 0) { unset($Struct); // Cleanup the Struct return 0; } $newStr = DLLStructGetData($Struct, "buf"); unset($Struct); // Cleanup the Struct return $newStr; }