home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 March / CMCD0304.ISO / Software / Freeware / Programare / nullsoft / nsis20.exe / Contrib / System / Source / System.c < prev    next >
C/C++ Source or Header  |  2003-09-11  |  40KB  |  1,331 lines

  1. // System.cpp : Defines the entry point for the DLL application.
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "Plugin.h"
  6. #include "Buffers.h"
  7. #include "System.h"
  8. #include <crtdbg.h>
  9.  
  10. // Parse Section Type 
  11. #define PST_PROC    0
  12. #define PST_PARAMS  1
  13. #define PST_RETURN  2
  14. #define PST_OPTIONS 3
  15.  
  16. #define PCD_NONE    0
  17. #define PCD_PROC    1
  18. #define PCD_PARAMS  2
  19. #define PCD_DONE    3   // Just Continue
  20.  
  21. const int ParamSizeByType[7] = {0, // PAT_VOID (Size will be equal to 1)
  22.     1, // PAT_INT
  23.     2, // PAT_LONG
  24.     1, // PAT_STRING
  25.     1, // PAT_WSTRING
  26.     1, // PAT_GUID
  27.     0}; // PAT_CALLBACK (Size will be equal to 1)
  28.  
  29. int z1, z2; // I've made them static for easier use at callback procs
  30. int LastStackPlace;
  31. int LastStackReal;
  32. DWORD LastError;
  33. volatile SystemProc *LastProc;
  34. int CallbackIndex;
  35. HINSTANCE g_hInstance;
  36.  
  37. // Return to callback caller with stack restore
  38. char retexpr[4];
  39. HANDLE retaddr;
  40.  
  41. char *GetResultStr(SystemProc *proc)
  42. {
  43.     char *buf = AllocString();
  44.     if (proc->ProcResult == PR_OK) lstrcpy(buf, "ok");
  45.     else if (proc->ProcResult == PR_ERROR) lstrcpy(buf, "error");
  46.     else if (proc->ProcResult == PR_CALLBACK) wsprintf(buf, "callback%d", proc->CallbackIndex);
  47.     return buf;
  48. }
  49.  
  50. #ifdef SYSTEM_LOG_DEBUG
  51.  
  52. // System log debuggin turned on
  53. #define SYSTEM_EVENT(a)  { _asm { mov logespsave, esp }; LogEvent(a); }
  54. #define SYSTEM_LOG_ADD(a)  { lstrcat(syslogbuf, a); }
  55. #define SYSTEM_LOG_POST     { lstrcat(syslogbuf, "\n"); WriteToLog(syslogbuf); *syslogbuf = 0; }
  56.  
  57. HANDLE logfile = NULL;
  58. char syslogbuf[4096] = "";
  59. int logop = 0, logespsave;
  60.  
  61. void WriteToLog(char *buffer)
  62. {
  63.     DWORD written;
  64.     char timebuffer[128];
  65.  
  66.     GetTickCount();
  67.  
  68.     if (logfile == NULL) return;
  69.  
  70.     SetFilePointer(logfile, 0, 0, FILE_END);
  71.  
  72.     wsprintf(timebuffer, "%04d  %04d.%03d    ", (++logop)%10000, (GetTickCount() / 1000) % 10000,
  73.         GetTickCount() % 1000);
  74.  
  75.     _RPT0(_CRT_WARN, timebuffer);
  76.     _RPT0(_CRT_WARN, buffer);
  77.  
  78.     WriteFile(logfile, timebuffer, lstrlen(timebuffer), &written, NULL);
  79.     WriteFile(logfile, buffer, lstrlen(buffer), &written, NULL);
  80. //    FlushFileBuffers(logfile);
  81. }
  82.  
  83. void LogEvent(char *a)
  84. {
  85.     char buffer[1024];
  86.     wsprintf(buffer, "%s  ESP = 0x%08X  Stack = 0x%08X  Real = 0x%08X", a, 
  87.         logespsave, LastStackPlace, LastStackReal);
  88.     SYSTEM_LOG_ADD(buffer);
  89. }
  90.  
  91. PLUGINFUNCTION(Debug)
  92. {
  93.     char *o1;
  94.     o1 = popstring();
  95.  
  96.     if (logfile == NULL)
  97.         if (lstrlen(o1) > 0)
  98.         {
  99.             SYSTEMTIME t;
  100.             char buffer[1024], buftime[1024], bufdate[1024];
  101.  
  102.             // Init debugging
  103.             logfile = CreateFile(o1, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 
  104.                 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  105.  
  106.             SetFilePointer(logfile, 0, 0, FILE_END);
  107.  
  108.             logop = 0;
  109.             GetLocalTime(&t);
  110.             GetTimeFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &t, NULL, buftime, 1024);
  111.             GetDateFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &t, NULL, bufdate, 1024);
  112.             wsprintf(buffer, "System, %s %s [build "__TIME__" "__DATE__"]\n", buftime, bufdate);
  113.             WriteToLog(buffer);
  114.         } else ;
  115.     else
  116.     if (lstrlen(o1) > 0)
  117.     {
  118.         // Log in to log file
  119.         WriteToLog(o1);
  120.     } else
  121.     {
  122.         // Stop debugging
  123.         WriteToLog("Debug stopped.\n\n\n");
  124.         CloseHandle(logfile);
  125.         logfile = NULL;
  126.     }
  127. } PLUGINFUNCTIONEND
  128.  
  129. #else
  130.  
  131. // System log debugging turned off
  132. #define SYSTEM_EVENT(a)
  133. #define SYSTEM_LOG_ADD(a)
  134. #define SYSTEM_LOG_POST
  135.  
  136. #endif
  137.  
  138. PLUGINFUNCTION(Get)
  139. {
  140.     SystemProc *proc = PrepareProc(FALSE);
  141.     SYSTEM_LOG_ADD("Get ");
  142.     SYSTEM_LOG_ADD(proc->DllName);
  143.     SYSTEM_LOG_ADD("::");
  144.     SYSTEM_LOG_ADD(proc->ProcName);
  145.     SYSTEM_LOG_ADD("\n");
  146.     SYSTEM_LOG_POST;
  147.     if ((proc->Options & POPT_ALWRETURN) != 0)
  148.     {
  149.         // Always return flag set -> return separate proc and result
  150.         pushint((int) proc);
  151.         GlobalFree(pushstring(GetResultStr(proc)));
  152.     } else
  153.     {
  154.         if (proc->ProcResult != PR_OK)
  155.         {
  156.             // No always return flag and error result - return result
  157.             GlobalFree(pushstring(GetResultStr(proc)));
  158.             // If proc is permanent?
  159.             if ((proc->Options & POPT_PERMANENT) == 0)
  160.                 GlobalFree((HANDLE) proc); // No, free it
  161.         }
  162.         else // Ok result, return proc
  163.             pushint((int) proc);
  164.     }
  165. } PLUGINFUNCTIONEND
  166.  
  167. PLUGINFUNCTION(Call)
  168. {
  169.     // Prepare input
  170.     SystemProc *proc = PrepareProc(TRUE);
  171.     SYSTEM_LOG_ADD("Call ");
  172.     SYSTEM_LOG_ADD(proc->DllName);
  173.     SYSTEM_LOG_ADD("::");
  174.     SYSTEM_LOG_ADD(proc->ProcName);
  175.     SYSTEM_LOG_ADD("\n");
  176.     if (proc->ProcResult != PR_CALLBACK)
  177.         ParamAllocate(proc);
  178.     ParamsIn(proc);
  179.  
  180.     // Make the call
  181.     if (proc->ProcResult != PR_ERROR)
  182.     {
  183.         switch (proc->ProcType)
  184.         {
  185.         case PT_NOTHING:
  186.             if (proc->ProcResult == PR_CALLBACK) 
  187.                 proc = CallBack(proc);
  188.             break;
  189.         case PT_PROC:
  190.         case PT_VTABLEPROC:
  191.             proc = CallProc(proc); break;
  192.         case PT_STRUCT:
  193.             CallStruct(proc); break;
  194.         }
  195.     }
  196.  
  197.     // Process output
  198.     if ((proc->Options & POPT_ALWRETURN) != 0)
  199.     {
  200.         // Always return flag set - return separate return and result
  201.         ParamsOut(proc);
  202.         GlobalFree(pushstring(GetResultStr(proc)));
  203.     } else
  204.     {
  205.         if (proc->ProcResult != PR_OK)
  206.         {
  207.             ProcParameter pp;
  208.             // Save old return param
  209.             pp = proc->Params[0];
  210.  
  211.             // Return result instead of return value
  212.             proc->Params[0].Value = (int) GetResultStr(proc);
  213.             proc->Params[0].Type = PAT_STRING;
  214.             // Return all params
  215.             ParamsOut(proc);
  216.  
  217.             // Restore old return param
  218.             proc->Params[0] = pp;
  219.         } else 
  220.             ParamsOut(proc);        
  221.     }
  222.  
  223.     if (proc->ProcResult != PR_CALLBACK)
  224.     {
  225.         // Deallocate params if not callback
  226.         ParamsDeAllocate(proc);
  227.  
  228.         // if not callback - check for unload library option
  229.         if ((proc->Options & POPT_UNLOAD) 
  230.             && (proc->ProcType == PT_PROC) 
  231.             && (proc->Dll != NULL)) 
  232.             FreeLibrary(proc->Dll); // and unload it :)
  233.  
  234.         // In case of POPT_ERROR - first pop will be proc error
  235.         if ((proc->Options & POPT_ERROR) != 0) pushint(LastError);
  236.     }    
  237.  
  238.     // If proc is permanent?
  239.     if ((proc->Options & POPT_PERMANENT) == 0)
  240.         GlobalFree((HANDLE) proc); // No, free it
  241. } PLUGINFUNCTIONEND
  242.  
  243. PLUGINFUNCTIONSHORT(Int64Op)
  244. {
  245.     __int64 i1, i2 = 0, i3, i4;
  246.     char *op, *o1, *o2;
  247.     char buf[128];
  248.  
  249.     // Get strings
  250.     o1 = popstring(); op = popstring(); 
  251.     i1 = myatoi(o1); // convert first arg to int64
  252.     if ((*op != '~') && (*op != '!'))
  253.     {
  254.         // get second arg, convert it, free it
  255.         o2 = popstring();
  256.         i2 = myatoi(o2); 
  257.         GlobalFree(o2);
  258.     }
  259.  
  260.     // operation
  261.     switch (*op)
  262.     {
  263.     case '+': i1 += i2; break;
  264.     case '-': i1 -= i2; break;
  265.     case '*': i1 *= i2; break;
  266.     case '/': 
  267.     case '%': 
  268.         // It's unclear, but in this case compiler will use DivMod rountine
  269.         // instead of two separate Div and Mod rountines.
  270.         if (i2 == 0) { i3 = 0; i4 = i1; }
  271.         else {i3 = i1 / i2; i4 = i1 % i2; }
  272.         if (*op == '/') i1 = i3; else i1 = i4; 
  273.         break;
  274.     case '|': if (op[1] == '|') i1 = i1 || i2; else i1 |= i2; break;
  275.     case '&': if (op[1] == '&') i1 = i1 && i2; else i1 &= i2; break;
  276.     case '^': i1 ^= i2; break;
  277.     case '~': i1 = ~i1; break;
  278.     case '!': i1 = !i1; break;
  279.     case '<': if (op[1] == '<') i1 = i1 << i2; else i1 = i1 < i2; break;
  280.     case '>': if (op[1] == '>') i1 = i1 >> i2; else i1 = i1 > i2; break;
  281.     case '=': i1 = (i1 == i2); break;
  282.     }
  283.     
  284.     // Output and freedom
  285.     myitoa64(i1, buf);
  286.     pushstring(buf);
  287.     GlobalFree(o1); GlobalFree(op);
  288. } PLUGINFUNCTIONEND
  289.  
  290. __int64 GetIntFromString(char **p)
  291. {
  292.     char buffer[128], *b = buffer;
  293.     (*p)++; // First character should be skipped
  294.     while (((**p >= 'a') && (**p <= 'f')) || ((**p >= 'A') && (**p <= 'F')) || ((**p >= '0') && (**p <= '9')) || (**p == 'X') || (**p == '-') || (**p == 'x') || (**p == '|')) *(b++) = *((*p)++);
  295.     *b = 0;
  296.     (*p)--; // We should point at last digit
  297.     return myatoi(buffer);
  298. }
  299.  
  300. SystemProc *PrepareProc(BOOL NeedForCall)
  301. {
  302.     int SectionType = PST_PROC, // First section is always proc spec
  303.         ProcType = PT_NOTHING, // Default proc spec
  304.         ChangesDone = 0,
  305.         ParamIndex = 0,
  306.         temp = 0, temp2, temp3, temp4;
  307.     SystemProc *proc = NULL;
  308.     char *ibuf, *ib, *sbuf, *cbuf, *cb;
  309.  
  310.     // Retrieve proc specs
  311.     cb = (cbuf = AllocString()); // Current String buffer
  312.     sbuf = AllocString(); // Safe String buffer
  313.     ib = ibuf = popstring(); // Input string
  314.  
  315.     // Parse the string
  316.     while (SectionType != -1)
  317.     {
  318.         // Check for Section Change
  319.         ChangesDone = SectionType;
  320.         switch (*ib)
  321.         {
  322.         case 0x0: SectionType = -1; break;
  323.         case '#': SectionType = PST_PROC; ProcType = PT_NOTHING; break;
  324.         case '(': 
  325.             SectionType = PST_PARAMS; 
  326.             // fake-real parameter: for COM interfaces first param is Interface Pointer
  327.             ParamIndex = ((ProcType == PT_VTABLEPROC)?(2):(1)); 
  328.             temp3 = temp = 0; 
  329.             break;
  330.         case ')': SectionType = PST_RETURN; temp3 = temp = 0; break;
  331.         case '?': SectionType = PST_OPTIONS; temp = 1; break;
  332.         }
  333.  
  334.         // Check for changes
  335.         if (ChangesDone != SectionType)
  336.         {
  337.             switch (ChangesDone)
  338.             {
  339.             case PST_PROC:
  340.                 *cb = 0;
  341.                 // Adopt proc
  342.                 if (proc == NULL)
  343.                 {
  344.                     proc = (SystemProc *) GlobalAlloc(GPTR, sizeof(SystemProc));
  345.                     proc->Options = 0;
  346.                     proc->ParamCount = 0;
  347.                 }
  348.                 // Default parameters
  349.                 *proc->DllName = 0;
  350.                 *proc->ProcName = 0;
  351.                 proc->Dll = NULL;
  352.                 proc->Proc = NULL;
  353.                 proc->ProcType = ProcType;
  354.                 proc->ProcResult = PR_OK;
  355.     
  356.                 // Section changed and previos section was Proc
  357.                 switch (ProcType)
  358.                 {
  359.                 case PT_NOTHING:
  360.                     // Is it previous proc or just unknown proc?
  361.                     if (cb != cbuf)
  362.                     {
  363.                         // Previous proc (for clear up)
  364.                         SystemProc *pr = NULL;
  365.  
  366.                         if (proc != NULL) GlobalFree(proc);
  367.                         // Get already defined proc                                      
  368.                         proc = (SystemProc *) myatoi(cbuf);
  369.  
  370.                         // Find the last clone at proc queue
  371.                         while (proc->Clone != NULL) proc = (pr = proc)->Clone;
  372.  
  373.                         // Clear parents record for child callback proc
  374.                         if (pr != NULL) pr->Clone = NULL;
  375.  
  376.                         // Never Redefine?
  377.                         if ((proc->Options & POPT_NEVERREDEF) != 0)
  378.                         {
  379.                             // Create new proc as copy
  380.                             proc = GlobalCopy(proc);
  381.                             // NeverRedef options is never inherited
  382.                             proc->Options &= (~POPT_NEVERREDEF) & (~POPT_PERMANENT);
  383.                         } else proc->Options |= POPT_PERMANENT; // Proc is old -> permanent
  384.                     }
  385.                     break;
  386.                 case PT_PROC:
  387.                 case PT_VTABLEPROC:
  388.                     lstrcpy(proc->ProcName, cbuf);
  389.                     lstrcpy(proc->DllName, sbuf);
  390.                     break;
  391.                 case PT_STRUCT:
  392.                     lstrcpy(proc->ProcName, cbuf);
  393.                     break;
  394.                 }
  395.                 continue;
  396.             case PST_PARAMS:
  397.                 proc->ParamCount = ParamIndex;
  398.             case PST_RETURN:
  399.             case PST_OPTIONS:
  400.                 continue;
  401.             }            
  402.         }
  403.  
  404.         // Parse the section
  405.         ChangesDone = PCD_NONE;
  406.         switch (SectionType)
  407.         {
  408.         // Proc sections parser
  409.         case PST_PROC:
  410.             switch (*ib)
  411.             {
  412.             case ':':
  413.             case '-':
  414.                 // Is it '::'
  415.                 if ((*(ib) == '-') && (*(ib+1) == '>'))
  416.                 {
  417.                     ProcType = PT_VTABLEPROC;    
  418.                 } else
  419.                 {
  420.                     if ((*(ib+1) != ':') || (*(ib) == '-')) break;
  421.                     ProcType = PT_PROC;
  422.                 }
  423.                 ib++; // Skip next ':'
  424.  
  425.                 if (cb > cbuf)
  426.                 {
  427.                     *cb = 0;
  428.                     lstrcpy(sbuf, cbuf);
  429.                 } else  *sbuf = 0; // No dll - system proc
  430.                 
  431.                 // Ok
  432.                 ChangesDone = PCD_DONE;
  433.                 break;
  434.             case '*':
  435.                 // Structure defenition
  436.                 ProcType = PT_STRUCT;
  437.                 ChangesDone = PCD_DONE;
  438.                 break;
  439.             }          
  440.             break;
  441.  
  442.         // Params and return sections parser
  443.         case PST_RETURN:
  444.             ParamIndex = 0; // Uses the same logic as PST_PARAMS section
  445.         case PST_PARAMS:
  446.             temp2 = -1; temp4 = 0; // Our type placeholder
  447.             switch (*ib)
  448.             {
  449.             case ' ':
  450.                 break;
  451.             case '_': // No param cutting specifier
  452.                 if (proc->ParamCount > ParamIndex) ParamIndex = proc->ParamCount;
  453.                 temp3 = temp = 0; // Clear parameter options
  454.                 break;
  455.             case ',': // Next param
  456.                 temp3 = temp = 0; // Clear parameter options
  457.                 ParamIndex++;
  458.                 break;
  459.             case '&':
  460.                 temp = 1; break; // Special parameter option
  461.             case '*':
  462.                 temp = -1; break; // Pointer parameter option
  463.  
  464.             // Types
  465.             case 'v':
  466.             case 'V': temp2 = PAT_VOID; break;
  467.             case 'i':
  468.             case 'I': temp2 = PAT_INT; break;
  469.             case 'l':
  470.             case 'L': temp2 = PAT_LONG; break;
  471.             case 't':
  472.             case 'T': temp2 = PAT_STRING; break;
  473.             case 'g':
  474.             case 'G': temp2 = PAT_GUID; break;
  475.             case 'w':
  476.             case 'W': temp2 = PAT_WSTRING; break;
  477.             case 'k':
  478.             case 'K': temp2 = PAT_CALLBACK; break;
  479.  
  480.             // Input output specifiers
  481.             case '.': temp3++; break; // skip specifier
  482.  
  483.             case 'R':
  484.                 temp4 = ((int) GetIntFromString(&ib))+1;
  485.                 if (temp4 < 11) temp4 += 10; 
  486.                 break;
  487.             case 'r': temp4 = ((int) GetIntFromString(&ib))+1; break; // Register
  488.  
  489.             case '-':
  490.             case '0': case '1': case '2': case '3': case '4':
  491.             case '5': case '6': case '7': case '8': case '9':
  492.                 // Numeric inline
  493.                 if (temp3 == 0)
  494.                 {
  495.                     ib--;
  496.                     // It's stupid, I know, but I'm too laze to do another thing
  497.                     myitoa64(GetIntFromString(&(ib)),(char *)(temp4 = (int) AllocString()));
  498.                 }
  499.                 break;
  500.  
  501.             case '\"': case '\'': case '`':
  502.                 // Character inline
  503.                 {
  504.                     char start = *ib;
  505.                     cb = cbuf;
  506.                     // copy inline
  507.                     while (!((*(++ib) == start) && (*(ib+1) != start)) && (*ib))
  508.                     {
  509.                         if ((*ib) == start) ++ib;
  510.                         *(cb++) = *(ib);
  511.                     }
  512.                     // finish and save
  513.                     *cb = 0; 
  514.                     temp4 = (int) AllocStr(cbuf);
  515.                 }
  516.                 break;
  517.  
  518.             case 's':
  519.             case 'S': temp4 = -1; break;    // Stack
  520.             case 'c':
  521.             case 'C': temp4 = INST_CMDLINE+1; break;
  522.             case 'd':
  523.             case 'D': temp4 = INST_INSTDIR+1; break;
  524.             case 'o':
  525.             case 'O': temp4 = INST_OUTDIR+1; break;
  526.             case 'e':
  527.             case 'E': temp4 = INST_EXEDIR+1; break;
  528.             case 'a':
  529.             case 'A': temp4 = INST_LANG+1; break;
  530.             }
  531.  
  532.             // Param type changed?
  533.             if (temp2 != -1)
  534.             {
  535.                 proc->Params[ParamIndex].Type = temp2;
  536.                 proc->Params[ParamIndex].Size = // If pointer, then 1, else by type
  537.                     (temp == -1)?(1):((ParamSizeByType[temp2]>0)?(ParamSizeByType[temp2]):(1));
  538.                 // Get the parameter real special option value
  539.                 if (temp == 1) temp = ((int) GetIntFromString(&ib)) + 1;
  540.                 proc->Params[ParamIndex].Option = temp;
  541.                 proc->Params[ParamIndex].Value = 0;
  542.                 proc->Params[ParamIndex].Input = IOT_NONE;
  543.                 proc->Params[ParamIndex].Output = IOT_NONE;
  544.             }
  545.           
  546.             // Param source/dest changed?
  547.             if (temp4 != 0)
  548.             {
  549.                 if (temp3 == 0)
  550.                 {
  551.                     // it may contain previous inline input
  552.                     if (!((proc->Params[ParamIndex].Input > -1) && (proc->Params[ParamIndex].Input <= __INST_LAST)))
  553.                         GlobalFree((HANDLE) proc->Params[ParamIndex].Input);
  554.                     proc->Params[ParamIndex].Input = temp4;
  555.                 }
  556.                 if (temp3 == 1)
  557.                     proc->Params[ParamIndex].Output = temp4;
  558.                 // Next parameter is output or something else
  559.                 temp3++;
  560.             }
  561.  
  562.             ChangesDone = PCD_DONE;
  563.             break;
  564.  
  565.         // Options sections parser
  566.         case PST_OPTIONS:
  567.             temp2 = 0;
  568.             switch (*ib)
  569.             {
  570.             case ' ':
  571.                 break;
  572.             case '!': temp = -temp; break;
  573.             case 'c':
  574.                 temp2 = POPT_CDECL;
  575.                 break;
  576.             case 'r':
  577.                 temp2 = POPT_ALWRETURN;
  578.                 break;
  579.             case 'n':
  580.                 temp2 = POPT_NEVERREDEF;
  581.                 break;
  582.             case 's':
  583.                 temp2 = POPT_GENSTACK;
  584.                 break;
  585.             case 'e':
  586.                 temp2 = POPT_ERROR;
  587.                 break;
  588.             case 'u':
  589.                 temp2 = POPT_UNLOAD;
  590.                 break;
  591.             }
  592.  
  593.             // New Options
  594.             if (temp2 != 0)
  595.             {
  596.                 if (temp == 1) proc->Options |= temp2;
  597.                 else proc->Options &= ~temp2;
  598.                 // Back to default (turn on nothing) state
  599.                 temp = 1; temp2 = 0;
  600.             }
  601.  
  602.             ChangesDone = PCD_DONE;
  603.             break;
  604.         }
  605.  
  606.         // Nothing done, just copy char to buffer
  607.         if (ChangesDone == PCD_NONE) *(cb++) = *(ib);
  608.         // Something done, buffer = ""
  609.         else cb = cbuf;
  610.  
  611.         // Increase input pointer
  612.         ib++;
  613.     }
  614.  
  615.     GlobalFree(ibuf);
  616.     GlobalFree(cbuf);
  617.     GlobalFree(sbuf);
  618.  
  619.     // Ok, the final step: check proc for existance
  620.     if (proc->Proc == NULL)
  621.     {
  622.         switch (proc->ProcType)
  623.         {
  624.         case PT_NOTHING: break;
  625.         case PT_VTABLEPROC:
  626.             {
  627.                 // Use direct system proc address
  628.                 int addr;
  629.   
  630.                 if ((proc->Dll = addr = (HANDLE) myatoi(proc->DllName)) == 0)
  631.                 {
  632.                     proc->ProcResult = PR_ERROR;
  633.                     break;
  634.                 }
  635.  
  636.                 // fake-real parameter: for COM interfaces first param is Interface Pointer
  637.                 proc->Params[1].Output = IOT_NONE;
  638.                 proc->Params[1].Input = AllocStr(proc->DllName);
  639.                 proc->Params[1].Size = 1;
  640.                 proc->Params[1].Type = PAT_INT;
  641.                 proc->Params[1].Option = 0;
  642.  
  643.                 // addr - pointer to interface vtable
  644.                 addr = *((int *)addr);
  645.                 // now addr contains the pointer to first item at VTABLE
  646.                 // add the index of proc
  647.                 addr = addr + (myatoi(proc->ProcName)*4);
  648.                 proc->Proc = *((HANDLE*)addr);
  649.             }
  650.             break;
  651.         case PT_PROC:
  652.             if (*proc->DllName == 0)
  653.             {
  654.                 // Use direct system proc address
  655.                 if ((proc->Proc = (HANDLE) myatoi(proc->ProcName)) == 0)
  656.                     proc->ProcResult = PR_ERROR;
  657.             } else
  658.             {
  659.                 // Get DLL address
  660.                 if ((proc->Dll = GetModuleHandle(proc->DllName)) == NULL)
  661.                     if ((proc->Dll = LoadLibrary(proc->DllName)) == NULL)
  662.                     {
  663.                         proc->ProcResult = PR_ERROR;
  664.                         break;
  665.                     }
  666.  
  667.                 // Get proc address
  668.                 if ((proc->Proc = GetProcAddress(proc->Dll, proc->ProcName)) == NULL)
  669.                 {
  670.                     // automatic A discover
  671.                     lstrcat(proc->ProcName, "A");
  672.                     if ((proc->Proc = GetProcAddress(proc->Dll, proc->ProcName)) == NULL)
  673.                         proc->ProcResult = PR_ERROR;                            
  674.                 }                    
  675.             }
  676.             break;
  677.         case PT_STRUCT:
  678.             if (*(proc->ProcName) != 0) proc->Proc = (HANDLE) myatoi(proc->ProcName);
  679.             break;
  680.         }
  681.     }
  682.  
  683.     return proc;
  684. }
  685.  
  686. void ParamAllocate(SystemProc *proc)
  687. {
  688.     int i;
  689.  
  690.     for (i = 0; i <= proc->ParamCount; i++)
  691.         if (((HANDLE) proc->Params[i].Value == NULL) && (proc->Params[i].Option == -1))
  692.         {
  693.             proc->Params[i].Value = (int) GlobalAlloc(GPTR, ParamSizeByType[proc->Params[i].Type]);
  694.         }
  695. }
  696.  
  697. void ParamsIn(SystemProc *proc)
  698. {
  699.     int i, *place;
  700.     char *realbuf;
  701.     LPWSTR wstr;
  702.  
  703.     i = (proc->ParamCount > 0)?(1):(0);
  704.     while (TRUE)
  705.     {
  706.         // Step 1: retrive value
  707.         if ((proc->Params[i].Input == IOT_NONE) || (proc->Params[i].Input == IOT_INLINE)) 
  708.             realbuf = AllocStr("");
  709.         else if (proc->Params[i].Input == IOT_STACK) realbuf = popstring();
  710.         else if ((proc->Params[i].Input > 0) && (proc->Params[i].Input <= __INST_LAST)) 
  711.             realbuf = getuservariable(proc->Params[i].Input - 1);
  712.         else 
  713.         {
  714.             // Inline input, will be freed as realbuf
  715.             realbuf = (char*) proc->Params[i].Input;
  716.             proc->Params[i].Input = IOT_INLINE;
  717.         }
  718.  
  719.         // Retreive pointer to place
  720.         if (proc->Params[i].Option == -1) place = (int*) proc->Params[i].Value;
  721.         else place = (int*) &(proc->Params[i].Value);
  722.  
  723.         // by default no blocks are allocated
  724.         proc->Params[i].allocatedBlock = NULL;
  725.  
  726.         // Step 2: place it
  727.         switch (proc->Params[i].Type)
  728.         {
  729.         case PAT_VOID:
  730.             proc->Params[i].Value = 0;
  731.             break;
  732.         case PAT_INT:
  733.             *((int*) place) = (int) myatoi(realbuf);
  734.             break;
  735.         case PAT_LONG:
  736.             *((__int64*) place) = myatoi(realbuf);
  737.             break;
  738.         case PAT_STRING:
  739. /*            if (proc->Params[i].Input == IOT_NONE) 
  740.                 *((int*) place) = (int) NULL;
  741.             else*/
  742.             *((int*) place) = (int) (proc->Params[i].allocatedBlock = AllocStr(realbuf));
  743.             break;
  744.         case PAT_WSTRING:
  745.         case PAT_GUID:
  746.             wstr = (LPWSTR) (proc->Params[i].allocatedBlock = GlobalAlloc(GPTR, g_stringsize*2));
  747.             MultiByteToWideChar(CP_ACP, 0, realbuf, g_stringsize, wstr, g_stringsize);
  748.             if (proc->Params[i].Type == PAT_GUID)
  749.             {
  750.                 *((HGLOBAL*)place) = (proc->Params[i].allocatedBlock = GlobalAlloc(GPTR, 16));
  751.                 CLSIDFromString(wstr, *((LPCLSID*)place));
  752.                 GlobalFree((HGLOBAL) wstr);
  753.             } else
  754.                 *((LPWSTR*)place) = wstr;
  755.             break;
  756.         case PAT_CALLBACK:
  757.             // Generate new or use old callback
  758.             if (lstrlen(realbuf) > 0)
  759.                 proc->Params[i].Value = (int) CreateCallback((SystemProc*) myatoi(realbuf));
  760.             break;
  761.         }
  762.         GlobalFree(realbuf);
  763.  
  764. #ifdef SYSTEM_LOG_DEBUG
  765.         {
  766.             char buf[1024];
  767.             wsprintf(buf, "\t\t\tParam In %d:    type %d value 0x%08X value2 0x%08X\n", i, 
  768.                 proc->Params[i].Type, proc->Params[i].Value, proc->Params[i]._value);
  769.             SYSTEM_LOG_ADD(buf);
  770.         }
  771. #endif
  772.  
  773.         if (i == 0) break;
  774.         if (i == proc->ParamCount) i = 0;
  775.         else i++;
  776.     } 
  777. }
  778.  
  779. void ParamsDeAllocate(SystemProc *proc)
  780. {
  781.     int i;
  782.  
  783.     for (i = proc->ParamCount; i >= 0; i--)
  784.         if (((HANDLE) proc->Params[i].Value != NULL) && (proc->Params[i].Option == -1))
  785.         {
  786. #ifndef _DEBUG
  787.             // I see no point for error debug version gives here
  788.             GlobalFree((HANDLE) (proc->Params[i].Value));
  789. #endif
  790.             proc->Params[i].Value = (int) NULL;
  791.         }
  792. }
  793.  
  794. void ParamsOut(SystemProc *proc)
  795. {
  796.     int i, *place;
  797.     char *realbuf;
  798.     LPWSTR wstr;
  799.  
  800.     i = proc->ParamCount;
  801.     do
  802.     {
  803.         // Retreive pointer to place
  804.         if (proc->Params[i].Option == -1) place = (int*) proc->Params[i].Value;
  805.         else place = (int*) &(proc->Params[i].Value);
  806.  
  807.         realbuf = AllocString();
  808.  
  809.         // Step 1: retrive value
  810.         switch (proc->Params[i].Type)
  811.         {
  812.         case PAT_VOID:
  813.             lstrcpy(realbuf,"");
  814.             break;
  815.         case PAT_INT:
  816.             wsprintf(realbuf, "%d", *((int*) place));
  817.             break;
  818.         case PAT_LONG:
  819.             myitoa64(*((__int64*) place), realbuf);
  820.             break;
  821.         case PAT_STRING:
  822.             {
  823.                 int num = lstrlen(*((char**) place));
  824.                 if (num >= g_stringsize) num = g_stringsize-1;
  825.                 lstrcpyn(realbuf,*((char**) place), num+1);
  826.                 realbuf[num] = 0;                
  827.             }
  828.             break;
  829.         case PAT_GUID:
  830.             wstr = (LPWSTR) GlobalAlloc(GPTR, g_stringsize*2);
  831.             StringFromGUID2(*((REFGUID*)place), wstr, g_stringsize*2);
  832.             WideCharToMultiByte(CP_ACP, 0, wstr, g_stringsize, realbuf, g_stringsize, NULL, NULL); 
  833.             GlobalFree((HGLOBAL)wstr);
  834.             break;
  835.         case PAT_WSTRING:
  836.             wstr = *((LPWSTR*)place);
  837.             WideCharToMultiByte(CP_ACP, 0, wstr, g_stringsize, realbuf, g_stringsize, NULL, NULL);             
  838.             break;
  839.         case PAT_CALLBACK:
  840.             wsprintf(realbuf, "%d", proc->Params[i].Value);
  841.             break;
  842.         }
  843.  
  844.         // memory cleanup
  845.         if ((proc->Params[i].allocatedBlock != NULL) && ((proc->ProcType != PT_STRUCT)
  846.             || (proc->Params[i].Option > 0)))
  847.             GlobalFree(proc->Params[i].allocatedBlock);
  848.  
  849.         // Step 2: place it
  850.         if (proc->Params[i].Output == IOT_NONE);
  851.         else if (proc->Params[i].Output == IOT_STACK) pushstring(realbuf);
  852.         else if (proc->Params[i].Output > 0) setuservariable(proc->Params[i].Output - 1, realbuf);
  853.  
  854.         GlobalFree(realbuf);
  855.  
  856.         i--;
  857.     } 
  858.     while (i >= 0);
  859. }
  860.  
  861. void _alloca_probe();
  862.  
  863. SystemProc __declspec(naked) *CallProc(SystemProc *proc)
  864. {
  865.     int z3;
  866.  
  867.     _asm
  868.     {
  869.         // Save stack
  870.         push    ebp
  871.         mov     ebp, esp
  872.         // Stack space for local variables
  873.         sub     esp, __LOCAL_SIZE   
  874.         // Save all usable registers to free our hands
  875.         push    ebx
  876.         push    edi
  877.         push    esi
  878.     }
  879.  
  880.     SYSTEM_LOG_ADD("\t\tCall:\n");
  881.     SYSTEM_EVENT("\t\t\tBefore call        ")
  882.  
  883.     if (CallbackIndex && (!(proc->Options & POPT_GENSTACK)))
  884.     {
  885.         _asm
  886.         {
  887.             push    ebp
  888.             // Save previous stack location
  889.             mov     LastStackReal, esp
  890.         }
  891.  
  892.         if (LastStackPlace == 0)
  893.         {
  894.             _asm
  895.             {
  896.                 // Create new stack
  897.                 mov     eax, NEW_STACK_SIZE
  898.                 call    _alloca_probe
  899.                 mov     LastStackPlace, esp
  900.             }
  901.         } else
  902.             _asm
  903.             {
  904.                 // Move stack pointer
  905.                 mov     esp, LastStackPlace
  906.             }
  907.     }
  908.  
  909.     // Push arguments to stack
  910.     for (z1 = proc->ParamCount; z1 > 0; z1--)
  911.     {
  912.         // Long types
  913.         if (proc->Params[z1].Size == 2)
  914.         {
  915.             z2 = proc->Params[z1]._value;
  916.             _asm    push    z2;
  917.         }
  918.         // Default
  919.         z2 = proc->Params[z1].Value;
  920.         _asm    push    z2;
  921.     }
  922.  
  923.     // Call the proc and save return
  924.     z1 = (int) proc->Proc;
  925.  
  926.     // Save proc
  927.     proc->Clone = LastProc;
  928.     _asm 
  929.     {
  930.         mov eax, proc
  931.         mov LastProc, eax
  932.     }
  933.     //LastProc = proc;
  934.  
  935.     SYSTEM_EVENT("\n\t\t\tNear call          ")
  936.     SYSTEM_LOG_POST;
  937.  
  938.     _asm
  939.     {
  940.         // Call
  941.         call    z1
  942.         // Return
  943.         mov     z1, eax
  944.         mov     z2, edx
  945.     }
  946.  
  947.     SYSTEM_LOG_ADD("Back from ");
  948.     SYSTEM_LOG_ADD(LastProc->ProcName);
  949.     SYSTEM_EVENT("\n\t\t\tShort-After call   ")
  950.  
  951.     if ((CallbackIndex) && (!(LastProc->Options & POPT_GENSTACK)))
  952.     {
  953.         _asm
  954.         {
  955.             // Restore real stack location
  956.             mov     LastStackPlace, esp
  957.             mov     esp, LastStackReal
  958.             pop     ebp
  959.         }
  960.     }
  961.  
  962.     // Restore proc
  963.     _asm 
  964.     {
  965.        mov eax, LastProc
  966.        mov proc, eax
  967.     }
  968. //    proc = LastProc;
  969.     LastProc = proc->Clone;
  970.  
  971.     // In case of cdecl convention we should clear stack
  972.     if ((proc->Options & POPT_CDECL) != 0)
  973.     {
  974.         if ((CallbackIndex > 0) && ((proc->Options & POPT_GENSTACK) == 0))
  975.         {
  976.             // In case of temporary stack
  977.             for (z3 = 1; z3 <= proc->ParamCount; z3++)
  978.                 LastStackPlace += 4*proc->Params[z3].Size;
  979.         } else
  980.         {
  981.             // in case of real stack
  982.             for (z3 = 1; z3 <= proc->ParamCount; z3++)
  983.             {   
  984.                 if (proc->Params[z3].Size == 2) 
  985.                     _asm    pop    edx;
  986.                 _asm    pop    edx;
  987.             }
  988.         }
  989.     }
  990.  
  991.     // In case of cleared call-proc-queue -> clear allocated stack place (more flexible)
  992.     if (LastProc == NULL) LastStackPlace = (int) NULL;
  993.  
  994.     // Save return
  995.     proc->Params[0].Value = z1;
  996.     if (proc->Params[0].Size == 2) 
  997.         proc->Params[0]._value = z2;
  998.     // Proc result: OK
  999.     proc->ProcResult = PR_OK;
  1000.  
  1001.     // In case of POPT_ERROR -> GetLastError
  1002.     if ((proc->Options & POPT_ERROR) != 0)
  1003.     {
  1004.         LastError = GetLastError();
  1005.     }
  1006.  
  1007.     SYSTEM_EVENT("\n\t\t\tAfter call         ")
  1008. #ifdef SYSTEM_LOG_DEBUG
  1009.     {
  1010.         char buf[1024];
  1011.         wsprintf(buf, "\n\t\t\tReturn              0x%08X    0x%08X", z1, z2);
  1012.         SYSTEM_LOG_ADD(buf);
  1013.     }
  1014. #endif
  1015.     SYSTEM_LOG_POST;
  1016.  
  1017.     _asm 
  1018.     {
  1019.         // Return
  1020.         mov     eax, proc
  1021.         // Restore registers
  1022.         pop     esi
  1023.         pop     edi
  1024.         pop     ebx
  1025.         // Restore stack pointer
  1026.         mov     esp, ebp
  1027.         pop     ebp
  1028.         // Return
  1029.         ret
  1030.     }
  1031. }
  1032.  
  1033. SystemProc __declspec(naked) *RealCallBack()
  1034. {
  1035.     SystemProc *proc;
  1036.     
  1037.     _asm 
  1038.     {
  1039.         // Save stack
  1040.         push    ebp
  1041.         mov     ebp, esp
  1042.         // Stack space for local variables
  1043.         sub     esp, __LOCAL_SIZE   
  1044.         // Save all usable registers to free our hands
  1045.         push    ebx
  1046.         push    edi
  1047.         push    esi
  1048.  
  1049.         // Arguments pointer
  1050.         mov     z2, esp    // 1-st arg - 4*4 (pushes) - 4 (return) - __LOCAL_SIZE
  1051.         add     z2, __LOCAL_SIZE
  1052.         add     z2, 5*4
  1053.         // Our callback proc
  1054.         mov     proc, eax
  1055.     }
  1056.  
  1057.     SYSTEM_LOG_ADD("Called callback from ");
  1058.     SYSTEM_LOG_ADD(LastProc->ProcName);
  1059.     SYSTEM_EVENT("\n\t\t\tShort-After call   ")
  1060.     SYSTEM_LOG_POST;
  1061.  
  1062.     // Find last unused clone
  1063.     while ((proc->Clone != NULL)) proc = proc->Clone;
  1064.     // 2. Create new clone
  1065.     proc = (proc->Clone = GlobalCopy(proc));
  1066.     // 3. Set clone option
  1067.     proc->Options |= POPT_CLONE;
  1068.  
  1069.     // Read arguments
  1070.     proc->ArgsSize = 0;
  1071.     for (z1 = 1; z1 <= proc->ParamCount; z1++)
  1072.     {
  1073.         // Default
  1074.         proc->Params[z1].Value = *(((int*)z2)++);
  1075.         proc->ArgsSize += 4;
  1076.         // Long only
  1077.         if (proc->Params[z1].Size == 2)
  1078.         {
  1079.             proc->Params[z1]._value = *(((int*)z2)++);
  1080.             proc->ArgsSize += 4;
  1081.         }
  1082.     }
  1083.     proc->ProcResult = PR_CALLBACK;
  1084.  
  1085.     _asm
  1086.     {
  1087.         // Return
  1088.         mov     eax, proc
  1089.  
  1090.         // Save temporary stack info
  1091.         push    ebp
  1092. //        push    LastStackPlace
  1093.         mov     LastStackPlace, esp
  1094.         // Restore real stack
  1095.         mov     esp, LastStackReal
  1096.         pop     ebp
  1097. //        pop     LastStackReal
  1098.     }
  1099.  
  1100.     _asm
  1101.     {
  1102.         // Fake return from System::Call
  1103.  
  1104.         // Restore registers
  1105.         pop     esi
  1106.         pop     edi
  1107.         pop     ebx
  1108.         // Restore stack pointer
  1109.         mov     esp, ebp
  1110.         pop     ebp
  1111.         // Return
  1112.         ret
  1113.     }
  1114. }
  1115.  
  1116.  
  1117. SystemProc __declspec(naked) *CallBack(SystemProc *proc)
  1118. {
  1119.     _asm 
  1120.     {
  1121.         // Save stack
  1122.         push    ebp
  1123.         mov     ebp, esp
  1124.         // Stack space for local variables
  1125.         sub     esp, __LOCAL_SIZE
  1126.         // Save all usable registers to free our hands
  1127.         push    ebx
  1128.         push    edi
  1129.         push    esi
  1130.     }
  1131.  
  1132.   // MessageBox(NULL, "cool1", "Cool", MB_OK);
  1133.  
  1134.     SYSTEM_LOG_ADD("\t\tReturn from callback:\n");
  1135.     SYSTEM_EVENT("\t\t\tBefore call-back   ");
  1136.     SYSTEM_LOG_POST;
  1137.  
  1138.     //z1 = proc->Params[0].Value;
  1139.     //z2 = proc->Params[0]._value;
  1140.     //z1 = &(proc->Params[0].Value);
  1141.     _asm
  1142.     {
  1143.         mov eax, proc
  1144.         add eax, SYSTEM_ZERO_PARAM_VALUE_OFFSET
  1145.         push [eax]
  1146.         push [eax+4]
  1147.     }
  1148.     
  1149.     // Adjust return statement
  1150.     if ((proc->Options & POPT_CDECL) == 0) retexpr[1] = proc->ArgsSize;
  1151.     else retexpr[1] = 0x0;
  1152.  
  1153.     // Right return statement address
  1154.     retaddr = (HANDLE) retexpr;
  1155.  
  1156.     // Remove unneeded callback proc
  1157.     GlobalFree((HANDLE) proc);
  1158.  
  1159. //    MessageBox(NULL, "cool2", "Cool", MB_OK);
  1160.  
  1161.     _asm
  1162.     {
  1163.         // Prepare return
  1164. //        mov    eax, z1
  1165.         //mov    edx, z2
  1166.  
  1167.         // Restore temporary stack and return
  1168.  
  1169.         // Save real stack info
  1170.         // Save previous stack location
  1171. //        push    LastStackReal
  1172.         push    ebp
  1173.         mov     LastStackReal, esp
  1174.         // Move stack pointer
  1175.         mov     esp, LastStackPlace
  1176. //        pop     LastStackPlace
  1177.         pop     ebp        
  1178.     }
  1179.         
  1180. #ifdef SYSTEM_LOG_DEBUG
  1181.     SYSTEM_EVENT("\n\t\t\tSh-Before call-back");
  1182.     SYSTEM_LOG_POST;        
  1183. #endif
  1184.  
  1185.     // Fake return from Callback
  1186.     _asm {
  1187.         // callback proc result
  1188.         pop edx
  1189.         pop eax
  1190.  
  1191.         // Restore registers
  1192.         pop     esi
  1193.         pop     edi
  1194.         pop     ebx
  1195.         // Restore stack pointer
  1196.         mov     esp, ebp
  1197.         pop     ebp
  1198.         // Return
  1199.         jmp     retaddr
  1200.     }
  1201. }
  1202.  
  1203. HANDLE CreateCallback(SystemProc *cbproc)
  1204. {
  1205.     char *mem;
  1206.  
  1207.     if (cbproc->Proc == NULL)
  1208.     {
  1209.         // Set callback index
  1210.         cbproc->CallbackIndex = ++(CallbackIndex);
  1211.         cbproc->Options |= POPT_PERMANENT;
  1212.  
  1213.         mem = (char *) (cbproc->Proc = GlobalAlloc(GPTR, 10));
  1214.         *(mem++) = 0xB8; // Mov eax, const
  1215.         *(((int *)mem)++) = (int) cbproc;
  1216.         *(mem++) = 0xe9; // Jmp relative
  1217.         *((int *)mem) = (int) RealCallBack;
  1218.         *((int *)mem) -= ((int) mem) + 4;
  1219.     }
  1220.  
  1221.     // Return proc address
  1222.     return cbproc->Proc;
  1223. }
  1224.  
  1225. void CallStruct(SystemProc *proc)
  1226. {
  1227.     BOOL ssflag;
  1228.     int i, structsize = 0, size = 0;
  1229.     char *st, *ptr;
  1230.  
  1231.     SYSTEM_LOG_ADD("\t\tStruct...");
  1232.  
  1233.     // Calculate the structure size 
  1234.     for (i = 1; i <= proc->ParamCount; i++)
  1235.         if (proc->Params[i].Option < 1)
  1236.             structsize += proc->Params[i].Size * 4;
  1237.         else
  1238.             structsize += proc->Params[i].Option-1;
  1239.     
  1240.     // Struct exists?
  1241.     if (proc->Proc == NULL)
  1242.         // No. Allocate struct memory
  1243.         proc->Proc = (HANDLE) GlobalAlloc(GPTR, structsize);
  1244.     else  // In case of zero size defined structure use mapped size 
  1245.         if (structsize == 0) structsize = (int) GlobalSize((HANDLE) proc->Proc);
  1246.     
  1247.     // Pointer to current data
  1248.     st = (char*) proc->Proc;
  1249.  
  1250.     for (i = 1; i <= proc->ParamCount; i++)
  1251.     {
  1252.         ssflag = FALSE;
  1253.  
  1254.         // Normal or special block?
  1255.         if (proc->Params[i].Option < 1)
  1256.         {
  1257.             // Normal
  1258.             size = proc->Params[i].Size*4;
  1259.             ptr = (char*) &(proc->Params[i].Value);
  1260.         }
  1261.         else
  1262.         {
  1263.             int intmask[4] = {0xFFFFFFFF, 0x000000FF, 0x0000FFFF, 0x00FFFFFF};
  1264.  
  1265.             // Special
  1266.             size = proc->Params[i].Option-1;
  1267.  
  1268.             switch (proc->Params[i].Type)
  1269.             {
  1270.             case PAT_VOID: ptr = NULL; break;
  1271.             case PAT_LONG: 
  1272.                 // real structure size
  1273.                 proc->Params[i].Value = structsize;
  1274.                 proc->Params[i]._value = 0;
  1275.                 ssflag = TRUE;
  1276.             case PAT_INT: 
  1277.                 // clear unused value bits
  1278.                 proc->Params[i].Value &= intmask[((size >= 0) && (size < 4))?(size):(0)];
  1279.                 // pointer
  1280.                 ptr = (char*) &(proc->Params[i].Value); 
  1281.                 break;
  1282.  
  1283.             case PAT_STRING: 
  1284.             case PAT_GUID: 
  1285.             case PAT_WSTRING: 
  1286.                 ptr = (char*) proc->Params[i].Value; break;
  1287.             }
  1288.         }
  1289.  
  1290.         // Process them!
  1291.         if (ptr != NULL)
  1292.         {
  1293.             // Input
  1294.             if ((proc->Params[i].Input != IOT_NONE) || (ssflag))
  1295.                 copymem(st, ptr, size);
  1296.  
  1297.             // Output
  1298.             if (proc->Params[i].Output != IOT_NONE)
  1299.                 copymem(ptr, st, size);
  1300.         }
  1301.  
  1302.         // Skip to next data block
  1303.         st += size;
  1304.     }
  1305.  
  1306.     SYSTEM_LOG_POST;
  1307.  
  1308.     // Proc virtual return - pointer to memory struct
  1309.     proc->Params[0].Value = (int) proc->Proc;
  1310. }
  1311.  
  1312. BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
  1313. {
  1314.         g_hInstance=hInst;
  1315.         
  1316.         if (ul_reason_for_call == DLL_PROCESS_ATTACH)
  1317.         {
  1318.             // initialize some variables
  1319.             LastStackPlace = 0;
  1320.             LastStackReal = 0;
  1321.             LastError = 0;
  1322.             LastProc = NULL;
  1323.             CallbackIndex = 0;
  1324.             retexpr[0] = 0xC2;
  1325.             retexpr[2] = 0x00;
  1326.         }
  1327.  
  1328.         return TRUE;
  1329. }
  1330.  
  1331.