BOOL PyTraceObject::ReadData(char **ppResult, int *retSize, int waitMilliseconds) { if (pMapBaseRead == NULL) { ReturnError("The module has not been setup for reading"); return FALSE; } if (waitMilliseconds!=0) { DWORD rc; Py_BEGIN_ALLOW_THREADS rc = WaitForSingleObject(hEvent, waitMilliseconds); Py_END_ALLOW_THREADS if (rc==WAIT_FAILED) { PyWin_SetAPIError("WaitForSingleObject", GetLastError()); return FALSE; } }
void ConfigRequest() { //validate the checksum if (input_data[1] != 0x55) { ReturnError(0x02); return; } //set the package-ID Response_Data[0] = 0x10; //Copy the config-data to the output buffer for (int i = 0; i < 13; i++) { Response_Data[i+1] = Config_Data[i]; } return; }
BOOL PyTraceObject::WriteData(const char *data, unsigned len) { if (pMapBaseWrite == NULL) { ReturnError("The module has not been setup for writing"); return FALSE; } BOOL rc = TRUE; Py_BEGIN_ALLOW_THREADS const char *data_this = data; while (len) { unsigned len_this = min(len, BUFFER_SIZE/2); BOOL ok = GetMyMutex(); if (ok) { // must use types with identical size on win32 and win64 unsigned long *pLen = (unsigned long *)pMapBaseWrite; unsigned long sizeLeft = (BUFFER_SIZE-sizeof(unsigned long)) - *pLen; // If less than double we need left, wait for it to empty, or .1 sec. if (sizeLeft < len_this * 2) { ReleaseMyMutex(); SetEvent(hEvent); WaitForSingleObject(hEventEmpty, 100); ok = GetMyMutex(); } } if (ok) { unsigned long *pLen = (unsigned long *)pMapBaseWrite; char *buffer = (char *)(((unsigned long *)pMapBaseWrite)+1); unsigned long sizeLeft = (BUFFER_SIZE-sizeof(unsigned long)) - *pLen; if (sizeLeft<len_this) *pLen = 0; memcpy(buffer+(*pLen), data_this, len_this); *pLen += len_this; rc = ReleaseMyMutex(); SetEvent(hEvent); data_this += len_this; len -= len_this; } } Py_END_ALLOW_THREADS return rc; }
static VOID ReturnOpenvpnOutput (HANDLE pipe, HANDLE ovpn_output, DWORD count, LPHANDLE events) { WCHAR *wide_output = NULL; CHAR output[512]; DWORD size; ReadFile (ovpn_output, output, sizeof (output), &size, NULL); if (size == 0) return; wide_output = malloc ((size) * sizeof (WCHAR)); if (wide_output) { MultiByteToWideChar (CP_UTF8, 0, output, size, wide_output, size); wide_output[size - 1] = 0; } ReturnError (pipe, ERROR_OPENVPN_STARTUP, wide_output, count, events); free (wide_output); }
MemoryCell * SubtractionOperator::ManageNumber(const MemoryCellNumber & mc1, const MemoryCell & mc2) { if (mc2.Type() == MemoryCell::NUMBER_MCT) return SINEWCLASS(MemoryCellNumber, (mc1.GetValue() - static_cast<const MemoryCellNumber &>(mc2).GetValue())); return ReturnError(CreateErrorMessage("Arithmetic Number - ", mc2)); }
// @pymethod [<o PyNETRESOURCE>, ...]|win32wnet|WNetEnumResource|Enumerates a list of resources static PyObject * PyWNetEnumResource(PyObject *self, PyObject *args) { // @rdesc The list contains PyNETRESOURCE entries. The total number of PyNETRESOURCE entries will be \<= number // requested (excepting the default behavior of requesting 0, which returns up to 64) // @comm Successive calls to win32wnet.WNetEnumResource will enumerate starting where the previous call // stopped. That is, the enumeration is not reset on successive calls UNLESS the enumeration handle is // closed and reopened. This lets you process an enumeration in small chunks (as small as 1 item at a time) // and still fully enumerate a network object! PyObject * Eob; // incoming Handle object from OpenEnum LPVOID lpBuffer; // buffer in virtual memory HANDLE hEnum; // handle from the OpenEnum call DWORD dwBuffsize; // size of lpBuffer DWORD dwRefsize; // reference size for virtualfree DWORD dwCount; // number of entries to get DWORD dwMaxCount = 64; DWORD Errno = 0; // @pyparm <o PyHANDLE>|handle||A handle to an open Enumeration Object (from <om win32wnet.WNetOpenEnum>) // @pyparm int|maxExtries|64|The maximum number of entries to return. if (!PyArg_ParseTuple(args, "O!|i", &PyHANDLEType, &Eob, &dwMaxCount)) // enforce the PyHANDLEType, Count is optional return NULL; if (!PyWinObject_AsHANDLE(Eob, &hEnum)) // shouldn't fail unless out of memory? return NULL; // nothing hard & fast here, just a rough sizing..have to figure out something better later if (dwMaxCount == 0) // using 0 to mean a default dwMaxCount = dwCount = 64; // lets default at 64 items else dwCount = dwMaxCount; // yes virginia, 0xffffffff is a LOT of items PyObject * pRetlist = PyList_New(0); //create a return list of 0 size if (pRetlist == NULL) // did we err? return NULL; do // start the enumeration { dwRefsize = dwBuffsize = 64*1024; // set size of buffer to request at 64K lpBuffer = VirtualAlloc(NULL, dwBuffsize, MEM_COMMIT, PAGE_READWRITE); // allocate out of Virtual Memory if (lpBuffer == NULL) // whoops, not that much!!?? { dwRefsize = dwBuffsize = 4 * 1024; //back off to 4K lpBuffer = VirtualAlloc(NULL, dwBuffsize, MEM_COMMIT, PAGE_READWRITE); if(lpBuffer == NULL) { Py_DECREF(pRetlist); PyErr_SetString(PyExc_MemoryError, "VirtualAlloc error in WNetEnumResource"); return NULL; } } Py_BEGIN_ALLOW_THREADS Errno = WNetEnumResource(hEnum, &dwCount, lpBuffer, &dwBuffsize); // do the enumeration Py_END_ALLOW_THREADS if (Errno == NO_ERROR) // if no error, then build the list { NETRESOURCE *p_nr = (NETRESOURCE *)lpBuffer; // Enum Resource returns a buffer of successive NETRESOURCE structs if (dwCount > 0) // we actually got something { dwMaxCount = dwMaxCount - dwCount; // how many more we will try to get do { PyObject *t_ob = PyWinObject_FromNETRESOURCE(p_nr); int listerr = PyList_Append(pRetlist,t_ob); // append our PyNETRESOURCE obj...Append does an INCREF! Py_DECREF(t_ob); if (listerr) // or bail { Py_DECREF(pRetlist); VirtualFree(lpBuffer, 0, MEM_RELEASE); return(ReturnError("Unable to create return list","WNetEnumResource")); } p_nr++; // next NETRESOURCE object (its a ++ because it is a typed pointer) dwCount--; } while (dwCount); }; // if dwCount = dwMaxCount; // reset to how many left } VirtualFree(lpBuffer, 0, MEM_RELEASE); // free the working buffer }while ((Errno == NO_ERROR) && (dwMaxCount != 0)); // No more because EnumResource returned "ERROR_NO_MORE_DATA" // or we have enumerated all that was asked for. return pRetlist; };
bool KLScript::Validate(const KLString& Script, KLVariables* Scoope) { KLVariables LocalVars(Scoope ? Scoope : &Variables); LastError = NO_ERROR; LastProcess = 0; LastReturn = NAN; if (SkipComment(Script) == Script.Size()) ReturnError(WRONG_SCRIPTCODE); while (true) { SkipComment(Script); switch (GetToken(Script)) { case SET: { IF_Terminated ReturnError(WRONG_PARAMETERS); if (!LocalVars.Exists(GetName(Script))) ReturnError(UNDEFINED_VARIABLE); if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); } break; case CALL: { IF_Terminated ReturnError(WRONG_PARAMETERS); if (!Bindings.Exists(GetName(Script))) ReturnError(UNDEFINED_FUNCTION); if (!Terminated) do { if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); } while (IS_NextParam); } break; case GOTO: { IF_Terminated ReturnError(WRONG_PARAMETERS); GetName(Script); if (!Terminated) do { if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); } while (IS_NextParam); } break; case VAR: case EXP: case POP: { IF_Terminated ReturnError(WRONG_PARAMETERS); do { if (KLString Name = GetName(Script)) { LocalVars.Add(Name); } else ReturnError(EMPTY_EXPRESSION); } while (IS_NextParam); } break; case T_IF: { IF_Terminated ReturnError(WRONG_PARAMETERS); if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); int Counter = 1; int Then = LastProcess; while (Counter && LastProcess) { LastProcess = Script.Find(';', LastProcess) + 1; if (LastProcess) switch (GetToken(Script)) { case T_IF: ++Counter; break; case T_ENDIF: --Counter; break; default: break; } } if (Counter) ReturnError(EXPECTED_ENDIF_TOK); LastProcess = Then; } break; case T_WHILE: { IF_Terminated ReturnError(WRONG_PARAMETERS); if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); int Counter = 1; int Then = LastProcess; while (Counter && LastProcess) { LastProcess = Script.Find(';', LastProcess) + 1; if (LastProcess) switch (GetToken(Script)) { case T_WHILE: ++Counter; break; case T_DONE: --Counter; break; default: break; } } if (Counter) ReturnError(EXPECTED_DONE_TOK); LastProcess = Then; } break; case T_DEF: { IF_Terminated ReturnError(WRONG_PARAMETERS); GetName(Script); if (Terminated) ++LastProcess; else ReturnError(WRONG_PARAMETERS); int Start = SkipComment(Script); int Stop = 0; int Counter = 1; while (Counter && LastProcess) { LastProcess = Stop = Script.Find(';', LastProcess) + 1; if (LastProcess) switch (GetToken(Script)) { case T_DEF: ++Counter; break; case T_END: --Counter; break; default: break; } } if (Counter) ReturnError(EXPECTED_DONE_TOK); const KLString Code = Script.Part(Start, Stop); int SavedLastProcess = LastProcess; if (!Code.Size()) ReturnError(EMPTY_FUNCTION); if (!Validate(Code)) return false; else LastProcess = SavedLastProcess; } break; case T_RETURN: { IF_Terminated ReturnError(WRONG_PARAMETERS); if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); } break; case UNKNOWN: ReturnError(UNKNOWN_EXPRESSION); break; case END: if (LastProcess == Script.Size()) return IS_NoError; else ReturnError(EMPTY_EXPRESSION); break; default: break; } if (Terminated) ++LastProcess; else ReturnError(EXPECTED_TERMINATOR); } return true; }
bool KLScript::Evaluate(const KLString& Script, KLList<double>* Params) { struct JUMP { int When; int Where; }; KLVariables LocalVars(&Variables); KLList<JUMP> Jumps; LastError = NO_ERROR; LastProcess = 0; LastReturn = NAN; Sigterm = false; if (SkipComment(Script) == Script.Size()) ReturnError(WRONG_SCRIPTCODE); while (true) { if (Sigterm) ReturnError(SCRIPT_TERMINATED); if (Jumps.Size() && Jumps.Last().When == LastProcess) LastProcess = Jumps.Pop().Where; int Start = SkipComment(Script); switch (OPERATION ID = GetToken(Script)) { case SET: { IF_Terminated ReturnError(WRONG_PARAMETERS); const KLString Var = GetName(Script); if (!LocalVars.Exists(Var)) ReturnError(UNDEFINED_VARIABLE); if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); KLVariables::KLVariable& Variable = LocalVars[Var]; if (Variable.IsReadonly()) ReturnError(VARIABLE_READONLY); Variable = Parser.GetValue(); } break; case CALL: { IF_Terminated ReturnError(WRONG_PARAMETERS); const KLString Proc = GetName(Script); KLList<double> Params; if (!Bindings.Exists(Proc)) ReturnError(UNDEFINED_FUNCTION); if (!Terminated) do { if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); Params.Insert(Parser.GetValue()); } while (IS_NextParam); if (IS_NoError) LastReturn = Bindings[Proc](Params); } break; case GOTO: { IF_Terminated ReturnError(WRONG_PARAMETERS); const KLString Proc = GetName(Script); KLList<double> Params; if (!Functions.Exists(Proc)) ReturnError(UNDEFINED_FUNCTION); if (!Terminated) do { if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); Params.Insert(Parser.GetValue()); } while (IS_NextParam); if (!IS_NoError) return false; else { int SavedLastProcess = LastProcess; Evaluate(Functions[Proc], &Params); LastProcess = SavedLastProcess; } } break; case VAR: case EXP: case POP: { IF_Terminated ReturnError(WRONG_PARAMETERS); do { if (KLString Name = GetName(Script)) { const bool Local = LocalVars.Exists(Name, false); if (ID == EXP) { const bool Global = Variables.Exists(Name); if (Local && !Global) { Variables.Add(Name, LocalVars[Name]); } else if (!Global) { Variables.Add(Name); } if (Local && !Global) LocalVars.Delete(Name); } else if (!Local) { LocalVars.Add(Name); } if (ID == POP && Params) LocalVars[Name] = Params->Dequeue(); } else ReturnError(EMPTY_EXPRESSION); } while (IS_NextParam); } break; case T_IF: { IF_Terminated ReturnError(WRONG_PARAMETERS); if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); int Counter = 1; int Then = LastProcess; int Else = 0; while (Counter && LastProcess) { LastProcess = Script.Find(';', LastProcess) + 1; if (LastProcess) switch (GetToken(Script)) { case T_IF: ++Counter; break; case T_ELSE: if (Counter == 1) Else = LastProcess; break; case T_ENDIF: --Counter; break; default: break; } } if (Counter) ReturnError(EXPECTED_ENDIF_TOK); if (Parser.GetValue()) { if (Else) Jumps.Insert({Else + 1, LastProcess + 1}); LastProcess = Then; } else if (Else) LastProcess = Else; } break; case T_WHILE: { IF_Terminated ReturnError(WRONG_PARAMETERS); if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); int Counter = 1; int Then = LastProcess; while (Counter && LastProcess) { LastProcess = Script.Find(';', LastProcess) + 1; if (LastProcess) switch (GetToken(Script)) { case T_WHILE: ++Counter; break; case T_DONE: --Counter; break; default: break; } } if (Counter) ReturnError(EXPECTED_DONE_TOK); if (Parser.GetValue()) { Jumps.Insert({LastProcess + 1, Start}); LastProcess = Then; } } break; case T_DEF: { IF_Terminated ReturnError(WRONG_PARAMETERS); const KLString Name = GetName(Script); if (Terminated) ++LastProcess; else ReturnError(WRONG_PARAMETERS); int Start = SkipComment(Script); int Stop = 0; int Counter = 1; while (Counter && LastProcess) { LastProcess = Stop = Script.Find(';', LastProcess) + 1; if (LastProcess) switch (GetToken(Script)) { case T_DEF: ++Counter; break; case T_END: --Counter; break; default: break; } } if (Counter) ReturnError(EXPECTED_DONE_TOK); const KLString Code = Script.Part(Start, Stop); int SavedLastProcess = LastProcess; if (!Code.Size()) ReturnError(EMPTY_FUNCTION); if (!Validate(Code, &LocalVars)) return false; else LastProcess = SavedLastProcess; if (Functions.Exists(Name)) Functions[Name] = Code; else Functions.Insert(Code, Name); } break; case T_RETURN: { IF_Terminated ReturnError(WRONG_PARAMETERS); if (!GetValue(Script, LocalVars)) ReturnError(WRONG_EVALUATION); LastReturn = Parser.GetValue(); return true; } break; case UNKNOWN: ReturnError(UNKNOWN_EXPRESSION); break; case END: if (LastProcess == Script.Size()) return IS_NoError; else ReturnError(EMPTY_EXPRESSION); break; case EXIT: return IS_NoError; default: break; } if (Terminated) ++LastProcess; else ReturnError(EXPECTED_TERMINATOR); } return true; }
//+------------------------------------------------------------------+ //| Построение сцены //+------------------------------------------------------------------+ SCFRESULT CScene::initialize(const int width, const int height) { SCFRESULT res=RES_S_OK; Shape cube; Shape ball; Shape plane; m_width =width; m_height=height; m_render.initialize(width, height); initiailizeMatrix(); // инициализируем окружение m_cube.program=compile_shaders("shaders\\skybox.vs.glsl", "shaders\\skybox.fs.glsl"); if(RES_FAIL(res=m_render.createShape(cube, m_cube))) ReturnError(res); if(RES_FAIL(res=m_texture_loader.loadTextureCubic("textures\\mountaincube.ktx", &m_cube.cube_map))) ReturnError(res); if(RES_FAIL(res=m_render.getUniforms(m_cube))) ReturnError(res); m_cube.view_matrix =m_view_matrix; // инициализируем шар if(RES_FAIL(res=m_shape_generator.createSphere(1, 40, 40, ball))) ReturnError(res); if(RES_FAIL(res=m_render.createShape(ball, m_ball))) ReturnError(res); m_ball.program =compile_shaders("shaders\\ball.vs.glsl", "shaders\\ball.fs.glsl"); m_ball.model_matrix =math::rotate(180.0f, 1.0f, 0.0f, 0.0f) *math::translate(0.0f, 2.0f, 0.0f); m_ball.proj_matrix =m_proj_matrix; m_ball.view_matrix =m_view_matrix; m_ball.light_position=m_light_position; m_ball.cube_map =m_cube.cube_map; if(RES_FAIL(res=m_texture_loader.loadTexturePng("textures\\ball_albedo.png", &m_ball.texture))) ReturnError(res); if(RES_FAIL(res=m_render.getUniforms(m_ball))) ReturnError(res); math::mat4 df=math::translate(0.0f, 2.0f, 0.0f); math::vec4 ss=math::vec4(0.0f, 0.0f, 0.0f, 1.0f)*((m_proj_matrix*m_view_matrix*m_ball.model_matrix).transpose()); DebugOutput("x=%d, y=%d\n", ss[0], ss[1]); // инициализируем плоскость if(RES_FAIL(res=m_shape_generator.createSquarePlane(10, plane))) ReturnError(res); if(RES_FAIL(res=m_render.createShape(plane, m_plane))) ReturnError(res); m_plane.program =compile_shaders("shaders\\table.vs.glsl", "shaders\\table.fs.glsl"); m_plane.model_matrix =math::translate(0.0f, -3.0f, 0.0f); m_plane.proj_matrix =m_proj_matrix; m_plane.view_matrix =m_view_matrix; m_plane.light_position=m_light_position; m_plane.shadow_matrix =m_shadow_sbpv_matrix * m_plane.model_matrix; if(RES_FAIL(res=m_texture_loader.loadTexturePng("textures\\table.png", &m_plane.texture))) ReturnError(res); if(RES_FAIL(res=m_render.getUniforms(m_plane))) ReturnError(res); m_shadow_program=compile_shaders("shaders\\light.vs.glsl", "shaders\\light.fs.glsl"); if(RES_FAIL(res=m_texture_loader.generateShadowTexture(&m_shadow_frame_buffer, &m_shadow_texture))) ReturnError(res); m_plane.texture_shadow=m_shadow_texture; m_ball.texture_shadow =m_shadow_texture; // инициализируем объекты для карты теней m_ball_shadow =m_ball; m_plane_shadow=m_plane; m_ball_shadow.program =0; m_ball_shadow.cube_map=0; m_ball_shadow.texture =0; m_plane_shadow.program=0; m_ball_shadow.proj_matrix =m_light_proj_matrix; m_ball_shadow.view_matrix =m_light_view_matrix; m_plane_shadow.proj_matrix=m_light_proj_matrix; m_plane_shadow.view_matrix=m_light_view_matrix; m_render.getUniforms(m_ball_shadow, &m_shadow_program); m_render.getUniforms(m_plane_shadow, &m_shadow_program); return(RES_S_OK); }
static BOOL GetStartupData (HANDLE pipe, STARTUP_DATA *sud) { size_t len; BOOL ret = FALSE; WCHAR *data = NULL; DWORD size, bytes, read; bytes = PeekNamedPipeAsync (pipe, 1, &exit_event); if (bytes == 0) { MsgToEventLog (M_SYSERR, TEXT("PeekNamedPipeAsync failed")); ReturnLastError (pipe, L"PeekNamedPipeAsync"); goto out; } size = bytes / sizeof (*data); data = malloc (bytes); if (data == NULL) { MsgToEventLog (M_SYSERR, TEXT("malloc failed")); ReturnLastError (pipe, L"malloc"); goto out; } read = ReadPipeAsync (pipe, data, bytes, 1, &exit_event); if (bytes != read) { MsgToEventLog (M_SYSERR, TEXT("ReadPipeAsync failed")); ReturnLastError (pipe, L"ReadPipeAsync"); goto out; } if (data[size - 1] != 0) { MsgToEventLog (M_ERR, TEXT("Startup data is not NULL terminated")); ReturnError (pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); goto out; } sud->directory = data; len = wcslen (sud->directory) + 1; size -= len; if (size <= 0) { MsgToEventLog (M_ERR, TEXT("Startup data ends at working directory")); ReturnError (pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); goto out; } sud->options = sud->directory + len; len = wcslen (sud->options) + 1; size -= len; if (size <= 0) { MsgToEventLog (M_ERR, TEXT("Startup data ends at command line options")); ReturnError (pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); goto out; } sud->std_input = sud->options + len; data = NULL; /* don't free data */ ret = TRUE; out: free (data); return ret; }
/* * Validate options against a white list. Also check the config_file is * inside the config_dir. The white list is defined in validate.c * Returns true on success */ static BOOL ValidateOptions (HANDLE pipe, const WCHAR *workdir, const WCHAR *options) { WCHAR **argv; int argc; WCHAR buf[256]; BOOL ret = FALSE; int i; const WCHAR *msg1 = L"You have specified a config file location (%s relative to %s)" " that requires admin approval. This error may be avoided" " by adding your account to the \"%s\" group"; const WCHAR *msg2 = L"You have specified an option (%s) that may be used" " only with admin approval. This error may be avoided" " by adding your account to the \"%s\" group"; argv = CommandLineToArgvW (options, &argc); if (!argv) { ReturnLastError (pipe, L"CommandLineToArgvW"); ReturnError (pipe, ERROR_STARTUP_DATA, L"Cannot validate options", 1, &exit_event); goto out; } /* Note: argv[0] is the first option */ if (argc < 1) /* no options */ { ret = TRUE; goto out; } /* * If only one argument, it is the config file */ if (argc == 1) { WCHAR *argv_tmp[2] = { L"--config", argv[0] }; if (!CheckOption (workdir, 2, argv_tmp, &settings)) { snwprintf (buf, _countof(buf), msg1, argv[0], workdir, settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } goto out; } for (i = 0; i < argc; ++i) { if (!IsOption(argv[i])) continue; if (!CheckOption (workdir, argc-i, &argv[i], &settings)) { if (wcscmp(L"--config", argv[i]) == 0 && argc-i > 1) { snwprintf (buf, _countof(buf), msg1, argv[i+1], workdir, settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } else { snwprintf (buf, _countof(buf), msg2, argv[i], settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } goto out; } } /* all options passed */ ret = TRUE; out: if (argv) LocalFree (argv); return ret; }
static VOID ReturnLastError (HANDLE pipe, LPCWSTR func) { ReturnError (pipe, GetLastError (), func, 1, &exit_event); }