/* =========== DI_GrabMouse =========== */ static void DI_GrabMouse(grab_t grab) { HRESULT hr; if (!di_initialized) { return; } if (di_grabbed == grab) { return; } if (grab == IN_GRAB) { Com_DPrintf("IDirectInputDevice_Acquire\n"); hr = IDirectInputDevice_Acquire(di_mouse); if (FAILED(hr)) { Com_EPrintf("Failed to acquire mouse, error 0x%lX\n", hr); } } else { Com_DPrintf("IDirectInputDevice_Unacquire\n"); hr = IDirectInputDevice_Unacquire(di_mouse); if (FAILED(hr)) { Com_EPrintf("Failed to unacquire mouse, error 0x%lX\n", hr); } } di_grabbed = grab; }
void SV_AutoSaveEnd(void) { if (sv.state != ss_game) return; if (no_save_games()) return; // save server state if (write_server_file(qtrue)) { Com_EPrintf("Couldn't write server file.\n"); return; } // clear whatever savegames are there if (wipe_save_dir(SAVE_AUTO)) { Com_EPrintf("Couldn't wipe '%s' directory.\n", SAVE_AUTO); return; } // copy off the level to the autosave slot if (copy_save_dir(SAVE_CURRENT, SAVE_AUTO)) { Com_EPrintf("Couldn't write '%s' directory.\n", SAVE_AUTO); return; } }
static void Sys_DeleteService_f(void) { char serviceName[256]; SC_HANDLE scm, service; DWORD error; if (Cmd_Argc() < 2) { Com_Printf("Usage: %s <servicename>\n", Cmd_Argv(0)); return; } scm = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); if (!scm) { error = GetLastError(); if (error == ERROR_ACCESS_DENIED) { Com_Printf("Insufficient privileges for opening Service Control Manager.\n"); } else { Com_EPrintf("%#lx opening Service Control Manager.\n", error); } return; } Q_concat(serviceName, sizeof(serviceName), "Q2PRO - ", Cmd_Argv(1), NULL); service = OpenService( scm, serviceName, DELETE); if (!service) { error = GetLastError(); if (error == ERROR_SERVICE_DOES_NOT_EXIST) { Com_Printf("Service doesn't exist.\n"); } else { Com_EPrintf("%#lx opening service.\n", error); } goto fail; } if (!DeleteService(service)) { error = GetLastError(); if (error == ERROR_SERVICE_MARKED_FOR_DELETE) { Com_Printf("Service has already been marked for deletion.\n"); } else { Com_EPrintf("%#lx deleting service.\n", error); } } else { Com_Printf("Service deleted successfully.\n"); } CloseServiceHandle(service); fail: CloseServiceHandle(scm); }
static void Sys_ConsoleInit(void) { DWORD mode; size_t width; #if USE_CLIENT if (!AllocConsole()) { Com_EPrintf("Couldn't create system console.\n"); return; } #elif USE_WINSVC if (statusHandle) { return; } #endif hinput = GetStdHandle(STD_INPUT_HANDLE); houtput = GetStdHandle(STD_OUTPUT_HANDLE); if (!GetConsoleScreenBufferInfo(houtput, &sbinfo)) { Com_EPrintf("Couldn't get console buffer info.\n"); return; } // determine terminal width width = sbinfo.dwSize.X; if (!width) { Com_EPrintf("Invalid console buffer width.\n"); return; } sys_con.widthInChars = width; sys_con.printf = Sys_Printf; gotConsole = qtrue; SetConsoleTitle(PRODUCT " console"); SetConsoleCtrlHandler(Sys_ConsoleCtrlHandler, TRUE); GetConsoleMode(hinput, &mode); mode |= ENABLE_WINDOW_INPUT; SetConsoleMode(hinput, mode); // figure out input line width width--; if (width > MAX_FIELD_TEXT - 1) { width = MAX_FIELD_TEXT - 1; } IF_Init(&sys_con.inputLine, width, width); Com_DPrintf("System console initialized (%d cols, %d rows).\n", sbinfo.dwSize.X, sbinfo.dwSize.Y); }
static qboolean Win_InitMouse( void ) { if( !win.wnd ) { return qfalse; } win.mouse.initialized = WIN_MOUSE_LEGACY; if( win_rawmouse->integer ) { if( !register_raw_mouse( /*RIDEV_NOLEGACY*/ 0 ) ) { Com_EPrintf( "RegisterRawInputDevices failed with error %#lx\n", GetLastError() ); Cvar_Set( "win_rawmouse", "0" ); } else { Com_Printf( "Raw mouse initialized.\n" ); win.mouse.initialized = WIN_MOUSE_RAW; } } if( win.mouse.initialized == WIN_MOUSE_LEGACY ) { win.mouse.parmsvalid = SystemParametersInfo( SPI_GETMOUSE, 0, win.mouse.originalparms, 0 ); win_xpfix->changed = win_xpfix_changed; Com_Printf( "Legacy mouse initialized.\n" ); } win_rawmouse->changed = win_rawmouse_changed; return qtrue; }
void SV_CheckForSavegame(mapcmd_t *cmd) { if (no_save_games()) return; if (read_level_file()) { // only warn when loading a regular savegame. autosave without level // file is ok and simply starts the map from the beginning. if (cmd->loadgame == 1) Com_EPrintf("Couldn't read level file.\n"); return; } if (cmd->loadgame) { // called from SV_Loadgame_f ge->RunFrame(); ge->RunFrame(); } else { int i; // coming back to a level after being in a different // level, so run it for ten seconds for (i = 0; i < 100; i++) ge->RunFrame(); } }
/* =============== HTTP_RunDownloads This calls curl_multi_perform do actually do stuff. Called every frame while connecting to minimise latency. Also starts new downloads if we're not doing the maximum already. =============== */ void HTTP_RunDownloads(void) { int new_count; CURLMcode ret; if (!curl_multi) return; start_next_download(); do { ret = curl_multi_perform(curl_multi, &new_count); if (new_count < curl_handles) { //hmm, something either finished or errored out. if (!finish_download()) return; //aborted curl_handles = new_count; } } while (ret == CURLM_CALL_MULTI_PERFORM); if (ret != CURLM_OK) { Com_EPrintf("[HTTP] Error running downloads: %s.\n", curl_multi_strerror(ret)); abort_downloads(); return; } start_next_download(); }
/* =========== DI_GetMouseEvents =========== */ static void DI_GetMouseEvents(void) { DIDEVICEOBJECTDATA data[16]; LPDIDEVICEOBJECTDATA p, last; DWORD numElements, button; int value; HRESULT hr; if (di_grabbed != IN_GRAB) { return; } do { numElements = 16; hr = IDirectInputDevice_GetDeviceData(di_mouse, sizeof(data[0]), data, &numElements, 0); if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) { IDirectInputDevice_Acquire(di_mouse); return; } if (FAILED(hr)) { Com_EPrintf("GetDeviceData failed with error 0x%lX\n", hr); return; } last = data + numElements; for (p = data; p < last; p++) { switch (p->dwOfs) { case DIMOFS_BUTTON0: case DIMOFS_BUTTON1: case DIMOFS_BUTTON2: case DIMOFS_BUTTON3: case DIMOFS_BUTTON4: case DIMOFS_BUTTON5: case DIMOFS_BUTTON6: case DIMOFS_BUTTON7: button = p->dwOfs - DIMOFS_BUTTON0; if (p->dwData & 0x80) { Key_Event(K_MOUSE1 + button, qtrue, p->dwTimeStamp); } else { Key_Event(K_MOUSE1 + button, qfalse, p->dwTimeStamp); } break; case DIMOFS_Z: value = p->dwData; if (!value) { break; } if (value > 0) { Key_Event(K_MWHEELUP, qtrue, p->dwTimeStamp); Key_Event(K_MWHEELUP, qfalse, p->dwTimeStamp); } else { Key_Event(K_MWHEELDOWN, qtrue, p->dwTimeStamp); Key_Event(K_MWHEELDOWN, qfalse, p->dwTimeStamp); } break; default: break; } } } while (hr == DI_BUFFEROVERFLOW); }
/* =============== HTTP_SetServer A new server is specified, so we nuke all our state. =============== */ void HTTP_SetServer(const char *url) { if (curl_multi) { Com_EPrintf("[HTTP] Set server without cleanup?\n"); return; } if (!*url) return; // ignore if downloads are permanently disabled if (allow_download->integer == -1) return; if (strncmp(url, "http://", 7)) { Com_Printf("[HTTP] Ignoring download server URL with non-HTTP schema.\n"); return; } curl_multi = curl_multi_init(); Q_strlcpy(download_server, url, sizeof(download_server)); Q_snprintf(download_referer, sizeof(download_referer), "quake2://%s", NET_AdrToString(&cls.serverAddress)); Com_Printf("[HTTP] Download server at %s\n", download_server); }
void *VID_GetCoreAddr(const char *sym) { void *entry; if (glw.hinstOpenGL) entry = (void *)GetProcAddress(glw.hinstOpenGL, sym); else entry = NULL; if (!entry) Com_EPrintf("Couldn't get OpenGL entry point: %s\n", sym); return entry; }
static void win_disablewinkey_changed( cvar_t *self ) { if( self->integer ) { win.kbdHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, hGlobalInstance, 0 ); if( !win.kbdHook ) { Com_EPrintf( "Couldn't set low-level keyboard hook, error %#lX\n", GetLastError() ); Cvar_Set( "win_disablewinkey", "0" ); } } else { if( win.kbdHook ) { UnhookWindowsHookEx( win.kbdHook ); win.kbdHook = NULL; } } }
void *VID_GetProcAddr(const char *sym) { void *entry; if (qwglGetProcAddress) entry = (void *)qwglGetProcAddress(sym); else entry = NULL; if (!entry) Com_EPrintf("Couldn't get OpenGL entry point: %s\n", sym); return entry; }
qboolean AL_Init( void ) { int i; if( !QAL_Init() ) { Com_EPrintf( "OpenAL failed to initialize.\n" ); return qfalse; } // check for linear distance extension if( !qalIsExtensionPresent( "AL_EXT_LINEAR_DISTANCE" ) ) { Com_EPrintf( "Required AL_EXT_LINEAR_DISTANCE extension is missing.\n" ); goto fail; } // generate source names qalGetError(); for( i = 0; i < MAX_CHANNELS; i++ ) { qalGenSources( 1, &s_srcnums[i] ); if( qalGetError() != AL_NO_ERROR ) { break; } } if( i < MIN_CHANNELS ) { Com_EPrintf( "Required at least %d sources, but got %d.\n", MIN_CHANNELS, i ); goto fail; } s_numchannels = i; Com_Printf( "OpenAL initialized.\n" ); return qtrue; fail: QAL_Shutdown(); return qfalse; }
/* ============== WAVE_Submit Send sound to device if buffer isn't really the dma buffer Also unlocks the dsound buffer =============== */ static void WAVE_Submit(void) { LPWAVEHDR h; int wResult; if (!dma.buffer) return; if (!wav_init) return; // // find which sound blocks have completed // while (1) { if (snd_completed == snd_sent) { Com_DPrintf("WAVE_Submit: Sound overrun\n"); break; } if (!(lpWaveHdr[snd_completed & WAV_MASK].dwFlags & WHDR_DONE)) { break; } snd_completed++; // this buffer has been played } // // submit a few new sound blocks // while (((snd_sent - snd_completed) >> sample16) < 8) { h = lpWaveHdr + (snd_sent & WAV_MASK); if (paintedtime / 256 <= snd_sent) break; snd_sent++; /* * Now the data block can be sent to the output device. The * waveOutWrite function returns immediately and waveform * data is sent to the output device in the background. */ wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR)); if (wResult != MMSYSERR_NOERROR) { Com_EPrintf("WAVE_Submit: Failed to write block to device\n"); WAVE_Shutdown(); return; } } }
static void raw_input_event( HANDLE handle ) { BYTE buffer[64]; UINT len, ret; PRAWINPUT ri; len = sizeof( buffer ); ret = GetRawInputData( handle, RID_INPUT, buffer, &len, sizeof( RAWINPUTHEADER ) ); if( ret == ( UINT )-1 ) { Com_EPrintf( "GetRawInputData failed with error %#lx\n", GetLastError() ); return; } ri = ( PRAWINPUT )buffer; if( ri->header.dwType == RIM_TYPEMOUSE ) { raw_mouse_event( &ri->data.mouse ); } }
/* =========== DI_GetMouseMotion =========== */ static qboolean DI_GetMouseMotion(int *dx, int *dy) { DIMOUSESTATE2 state; HRESULT hr; if (di_grabbed != IN_GRAB) { return qfalse; } hr = IDirectInputDevice_GetDeviceState(di_mouse, sizeof(state), &state); if (FAILED(hr)) { Com_EPrintf("GetDeviceState failed with error 0x%lX\n", hr); return qfalse; } *dx = state.lX; *dy = state.lY; return qtrue; }
qboolean AL_Init(void) { int i; Com_DPrintf("Initializing OpenAL\n"); if (!QAL_Init()) { goto fail0; } // check for linear distance extension if (!qalIsExtensionPresent("AL_EXT_LINEAR_DISTANCE")) { Com_SetLastError("AL_EXT_LINEAR_DISTANCE extension is missing"); goto fail1; } // generate source names qalGetError(); for (i = 0; i < MAX_CHANNELS; i++) { qalGenSources(1, &s_srcnums[i]); if (qalGetError() != AL_NO_ERROR) { break; } } Com_DPrintf("Got %d AL sources\n", i); if (i < MIN_CHANNELS) { Com_SetLastError("Insufficient number of AL sources"); goto fail1; } s_numchannels = i; Com_Printf("OpenAL initialized.\n"); return qtrue; fail1: QAL_Shutdown(); fail0: Com_EPrintf("Failed to initialize OpenAL: %s\n", Com_GetLastError()); return qfalse; }
/* =============== HTTP_FetchFile Fetches data from an arbitrary URL in a blocking fashion. Doesn't touch any global variables and thus doesn't interfere with existing client downloads. =============== */ ssize_t HTTP_FetchFile(const char *url, void **data) { dlhandle_t tmp; CURL *curl; CURLcode ret; long response; *data = NULL; curl = curl_easy_init(); if (!curl) return -1; memset(&tmp, 0, sizeof(tmp)); curl_easy_setopt(curl, CURLOPT_ENCODING, ""); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &tmp); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, recv_func); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt(curl, CURLOPT_PROXY, cl_http_proxy->string); curl_easy_setopt(curl, CURLOPT_USERAGENT, com_version->string); curl_easy_setopt(curl, CURLOPT_URL, url); ret = curl_easy_perform(curl); if (ret == CURLE_HTTP_RETURNED_ERROR) curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); curl_easy_cleanup(curl); if (ret == CURLE_OK) { *data = tmp.buffer; return tmp.position; } Com_EPrintf("[HTTP] Failed to fetch '%s': %s\n", url, ret == CURLE_HTTP_RETURNED_ERROR ? http_strerror(response) : curl_easy_strerror(ret)); if (tmp.buffer) Z_Free(tmp.buffer); return -1; }
void SV_AutoSaveBegin(mapcmd_t *cmd) { byte bitmap[MAX_CLIENTS / CHAR_BIT]; edict_t *ent; int i; // check for clearing the current savegame if (cmd->endofunit) { wipe_save_dir(SAVE_CURRENT); return; } if (sv.state != ss_game) return; if (no_save_games()) return; memset(bitmap, 0, sizeof(bitmap)); // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells for (i = 0; i < sv_maxclients->integer; i++) { ent = EDICT_NUM(i + 1); if (ent->inuse) { Q_SetBit(bitmap, i); ent->inuse = qfalse; } } // save the map just exited if (write_level_file()) Com_EPrintf("Couldn't write level file.\n"); // we must restore these for clients to transfer over correctly for (i = 0; i < sv_maxclients->integer; i++) { ent = EDICT_NUM(i + 1); ent->inuse = Q_IsBitSet(bitmap, i); } }
// optionally load the entity string from external source static void override_entity_string( const char *server ) { char *path = map_override_path->string; char buffer[MAX_QPATH], *str; ssize_t len; if( !*path ) { return; } len = Q_concat( buffer, sizeof( buffer ), path, server, ".ent", NULL ); if( len >= sizeof( buffer ) ) { len = Q_ERR_NAMETOOLONG; goto fail1; } len = SV_LoadFile( buffer, ( void ** )&str ); if( !str ) { if( len == Q_ERR_NOENT ) { return; } goto fail1; } if( len > MAX_MAP_ENTSTRING ) { len = Q_ERR_FBIG; goto fail2; } Com_Printf( "Loaded entity string from %s\n", buffer ); sv.entitystring = str; return; fail2: SV_FreeFile( str ); fail1: Com_EPrintf( "Couldn't load entity string from %s: %s\n", buffer, Q_ErrorString( len ) ); }
/* ================== SV_Trace Moves the given mins/maxs volume through the world from start to end. Passedict and edicts owned by passedict are explicitly not checked. ================== */ trace_t q_gameabi SV_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask) { trace_t trace; if (!sv.cm.cache) { Com_Error(ERR_DROP, "%s: no map loaded", __func__); } // work around game bugs if (++sv.tracecount > 10000) { Com_EPrintf("%s: runaway loop avoided\n", __func__); memset(&trace, 0, sizeof(trace)); trace.fraction = 1; trace.ent = ge->edicts; VectorCopy(end, trace.endpos); sv.tracecount = 0; return trace; } if (!mins) mins = vec3_origin; if (!maxs) maxs = vec3_origin; // clip to world CM_BoxTrace(&trace, start, end, mins, maxs, sv.cm.cache->nodes, contentmask); trace.ent = ge->edicts; if (trace.fraction == 0) { return trace; // blocked by the world } // clip to other solid entities SV_ClipMoveToEntities(start, mins, maxs, end, passedict, contentmask, &trace); return trace; }
static int SetupGL(int colorbits, int depthbits, int stencilbits, int multisamples) { PIXELFORMATDESCRIPTOR pfd; int pixelformat; // create the main window Win_Init(); if (colorbits == 0) colorbits = 24; if (depthbits == 0) depthbits = colorbits > 16 ? 24 : 16; if (depthbits < 24) stencilbits = 0; // choose pixel format if (qwglChoosePixelFormatARB && multisamples > 1) { int iAttributes[20]; UINT numFormats; iAttributes[0] = WGL_DRAW_TO_WINDOW_ARB; iAttributes[1] = TRUE; iAttributes[2] = WGL_SUPPORT_OPENGL_ARB; iAttributes[3] = TRUE; iAttributes[4] = WGL_DOUBLE_BUFFER_ARB; iAttributes[5] = TRUE; iAttributes[6] = WGL_PIXEL_TYPE_ARB; iAttributes[7] = WGL_TYPE_RGBA_ARB; iAttributes[8] = WGL_COLOR_BITS_ARB; iAttributes[9] = colorbits; iAttributes[10] = WGL_DEPTH_BITS_ARB; iAttributes[11] = depthbits; iAttributes[12] = WGL_STENCIL_BITS_ARB; iAttributes[13] = stencilbits; iAttributes[14] = WGL_SAMPLE_BUFFERS_ARB; iAttributes[15] = 1; iAttributes[16] = WGL_SAMPLES_ARB; iAttributes[17] = multisamples; iAttributes[18] = 0; iAttributes[19] = 0; if (qwglChoosePixelFormatARB(win.dc, iAttributes, NULL, 1, &pixelformat, &numFormats) == FALSE) { ReportLastError("wglChoosePixelFormatARB"); goto soft; } if (numFormats == 0) { Com_EPrintf("No suitable OpenGL pixelformat found for %d multisamples\n", multisamples); goto soft; } } else { memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = colorbits; pfd.cDepthBits = depthbits; pfd.cStencilBits = stencilbits; pfd.iLayerType = PFD_MAIN_PLANE; if (glw.minidriver) { if ((pixelformat = qwglChoosePixelFormat(win.dc, &pfd)) == 0) { ReportLastError("wglChoosePixelFormat"); goto soft; } } else { if ((pixelformat = ChoosePixelFormat(win.dc, &pfd)) == 0) { ReportLastError("ChoosePixelFormat"); goto soft; } } } // set pixel format if (glw.minidriver) { qwglDescribePixelFormat(win.dc, pixelformat, sizeof(pfd), &pfd); ReportPixelFormat(pixelformat, &pfd); if (qwglSetPixelFormat(win.dc, pixelformat, &pfd) == FALSE) { ReportLastError("wglSetPixelFormat"); goto soft; } } else { DescribePixelFormat(win.dc, pixelformat, sizeof(pfd), &pfd); ReportPixelFormat(pixelformat, &pfd); if (SetPixelFormat(win.dc, pixelformat, &pfd) == FALSE) { ReportLastError("SetPixelFormat"); goto soft; } } // check for software emulation if (pfd.dwFlags & PFD_GENERIC_FORMAT) { if (!gl_allow_software->integer) { Com_EPrintf("No hardware OpenGL acceleration detected\n"); goto soft; } Com_WPrintf("...using software emulation\n"); } else if (pfd.dwFlags & PFD_GENERIC_ACCELERATED) { Com_DPrintf("...MCD acceleration found\n"); win.flags |= QVF_ACCELERATED; } else { Com_DPrintf("...ICD acceleration found\n"); win.flags |= QVF_ACCELERATED; } // startup the OpenGL subsystem by creating a context and making it current if ((glw.hGLRC = qwglCreateContext(win.dc)) == NULL) { ReportLastError("wglCreateContext"); goto hard; } if (qwglMakeCurrent(win.dc, glw.hGLRC) == FALSE) { ReportLastError("wglMakeCurrent"); qwglDeleteContext(glw.hGLRC); glw.hGLRC = NULL; goto hard; } return FAIL_OK; soft: // it failed, clean up Win_Shutdown(); return FAIL_SOFT; hard: Win_Shutdown(); return FAIL_HARD; }
/* =========== DI_StartupMouse =========== */ static qboolean DI_InitMouse(void) { HRESULT hr; if (!win.wnd) { return qfalse; } Com_Printf("Initializing DirectInput\n"); if (!hDirectInput) { hDirectInput = LoadLibrary("dinput.dll"); if (!hDirectInput) { Com_EPrintf("Failed to load dinput.dll\n"); return qfalse; } pDirectInputCreate = (LPDIRECTINPUTCREATE) GetProcAddress(hDirectInput, "DirectInputCreateA"); if (!pDirectInputCreate) { Com_EPrintf("Failed to obtain DirectInputCreate\n"); goto fail; } } hr = pDirectInputCreate(hGlobalInstance, DIRECTINPUT_VERSION, &di, NULL); if (FAILED(hr)) { Com_EPrintf("DirectInputCreate failed with error 0x%lX\n", hr); goto fail; } hr = IDirectInput_CreateDevice(di, &_GUID_SysMouse, &di_mouse, NULL); if (FAILED(hr)) { Com_EPrintf("CreateDevice failed with error 0x%lX\n", hr); goto fail; } hr = IDirectInputDevice_SetDataFormat(di_mouse, &mouseDataFormat); if (FAILED(hr)) { Com_EPrintf("SetDataFormat failed with error 0x%lX\n", hr); goto fail; } hr = IDirectInputDevice_SetCooperativeLevel(di_mouse, win.wnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND); if (FAILED(hr)) { Com_EPrintf("SetCooperativeLevel failed with error 0x%lX\n", hr); goto fail; } hr = IDirectInputDevice_SetProperty(di_mouse, DIPROP_BUFFERSIZE, &mouseBufferSize.diph); if (FAILED(hr)) { Com_EPrintf("SetProperty failed with error 0x%lX\n", hr); goto fail; } di_initialized = qtrue; return qtrue; fail: if (di_mouse) { IDirectInputDevice_Release(di_mouse); di_mouse = NULL; } if (di) { IDirectInput_Release(di); di = NULL; } return qfalse; }
/* ============= Com_Error Both client and server can use this, and it will do the apropriate things. ============= */ void Com_Error(error_type_t code, const char *fmt, ...) { char msg[MAXERRORMSG]; va_list argptr; size_t len; // may not be entered recursively if (com_errorEntered) { #ifdef _DEBUG if (com_debug_break && com_debug_break->integer) { Sys_DebugBreak(); } #endif Sys_Error("recursive error after: %s", com_errorMsg); } com_errorEntered = qtrue; va_start(argptr, fmt); len = Q_vscnprintf(msg, sizeof(msg), fmt, argptr); va_end(argptr); // save error msg // can't print into it directly since it may // overlap with one of the arguments! memcpy(com_errorMsg, msg, len + 1); // fix up drity message buffers MSG_Init(); // abort any console redirects Com_AbortRedirect(); // reset Com_Printf recursion level com_printEntered = 0; X86_POP_FPCW; if (code == ERR_DISCONNECT || code == ERR_RECONNECT) { Com_WPrintf("%s\n", com_errorMsg); SV_Shutdown(va("Server was killed: %s\n", com_errorMsg), code); CL_Disconnect(code); goto abort; } #ifdef _DEBUG if (com_debug_break && com_debug_break->integer) { Sys_DebugBreak(); } #endif // make otherwise non-fatal errors fatal if (com_fatal_error && com_fatal_error->integer) { code = ERR_FATAL; } if (code == ERR_DROP) { Com_EPrintf("********************\n" "ERROR: %s\n" "********************\n", com_errorMsg); SV_Shutdown(va("Server crashed: %s\n", com_errorMsg), ERR_DROP); CL_Disconnect(ERR_DROP); goto abort; } if (com_logFile) { FS_FPrintf(com_logFile, "FATAL: %s\n", com_errorMsg); } SV_Shutdown(va("Server fatal crashed: %s\n", com_errorMsg), ERR_FATAL); CL_Shutdown(); NET_Shutdown(); logfile_close(); FS_Shutdown(); Sys_Error("%s", com_errorMsg); // doesn't get there abort: if (com_logFile) { FS_Flush(com_logFile); } com_errorEntered = qfalse; longjmp(abortframe, -1); }
static int LoadGL(const char *driver) { int colorbits = Cvar_ClampInteger(gl_colorbits, 0, 32); int depthbits = Cvar_ClampInteger(gl_depthbits, 0, 32); int stencilbits = Cvar_ClampInteger(gl_stencilbits, 0, 8); int multisamples = Cvar_ClampInteger(gl_multisamples, 0, 32); int ret; // figure out if we're running on a minidriver or not if (!Q_stricmp(driver, "opengl32") || !Q_stricmp(driver, "opengl32.dll")) { glw.minidriver = qfalse; } else { Com_Printf("...running a minidriver: %s\n", driver); glw.minidriver = qtrue; } // load the OpenGL library and bind to it if (!WGL_Init(driver)) { ReportLastError("WGL_Init"); return FAIL_SOFT; } // check if basic WGL entry points are present if (!qwglCreateContext || !qwglMakeCurrent || !qwglDeleteContext) { Com_EPrintf("Required WGL entry points are missing\n"); goto fail; } if (glw.minidriver) { // check if MCD entry points are present if using a minidriver if (!qwglChoosePixelFormat || !qwglSetPixelFormat || !qwglDescribePixelFormat || !qwglSwapBuffers) { Com_EPrintf("Required MCD entry points are missing\n"); goto fail; } } // check for WGL_ARB_multisample by creating a fake window if (multisamples > 1) { unsigned extensions = GetFakeWindowExtensions(); if (extensions & QWGL_ARB_multisample) { if (qwglChoosePixelFormatARB) { Com_Printf("...enabling WGL_ARB_multisample\n"); } else { Com_Printf("...ignoring WGL_ARB_multisample, WGL_ARB_pixel_format not found\n"); Cvar_Set("gl_multisamples", "0"); multisamples = 0; } } else { Com_Printf("WGL_ARB_multisample not found\n"); Cvar_Set("gl_multisamples", "0"); multisamples = 0; } } // create window, choose PFD, setup OpenGL context ret = SetupGL(colorbits, depthbits, stencilbits, multisamples); // attempt to recover if (ret == FAIL_SOFT && (colorbits || depthbits || stencilbits || multisamples > 1)) { Cvar_Set("gl_multisamples", "0"); ret = SetupGL(0, 0, 0, 0); } if (ret) goto fail; return FAIL_OK; fail: // it failed, clean up WGL_Shutdown(); return FAIL_SOFT; }
static void logfile_write(print_type_t type, const char *s) { char text[MAXPRINTMSG]; char buf[MAX_QPATH]; char *p, *maxp; size_t len; ssize_t ret; int c; if (logfile_prefix->string[0]) { p = strchr(logfile_prefix->string, '@'); if (p) { // expand it in place, hacky switch (type) { case PRINT_TALK: *p = 'T'; break; case PRINT_DEVELOPER: *p = 'D'; break; case PRINT_WARNING: *p = 'W'; break; case PRINT_ERROR: *p = 'E'; break; case PRINT_NOTICE: *p = 'N'; break; default: *p = 'A'; break; } } len = format_local_time(buf, sizeof(buf), logfile_prefix->string); if (p) { *p = '@'; } } else { len = 0; } p = text; maxp = text + sizeof(text) - 1; while (*s) { if (com_logNewline) { if (len > 0 && p + len < maxp) { memcpy(p, buf, len); p += len; } com_logNewline = qfalse; } if (p == maxp) { break; } c = *s++; if (c == '\n') { com_logNewline = qtrue; } else { c = Q_charascii(c); } *p++ = c; } *p = 0; len = p - text; ret = FS_Write(text, len, com_logFile); if (ret != len) { // zero handle BEFORE doing anything else to avoid recursion qhandle_t tmp = com_logFile; com_logFile = 0; FS_FCloseFile(tmp); Com_EPrintf("Couldn't write console log: %s\n", Q_ErrorString(ret)); Cvar_Set("logfile", "0"); } }
// A download finished, find out what it was, whether there were any errors and // if so, how severe. If none, rename file and other such stuff. static qboolean finish_download(void) { int msgs_in_queue; CURLMsg *msg; CURLcode result; dlhandle_t *dl; CURL *curl; long response; double sec, bytes; char size[16], speed[16]; char temp[MAX_OSPATH]; qboolean fatal_error = qfalse; const char *err; print_type_t level; do { msg = curl_multi_info_read(curl_multi, &msgs_in_queue); if (!msg) break; if (msg->msg != CURLMSG_DONE) continue; curl = msg->easy_handle; dl = find_handle(curl); cls.download.current = NULL; cls.download.percent = 0; //filelist processing is done on read if (dl->file) { fclose(dl->file); dl->file = NULL; } curl_handles--; result = msg->data.result; switch (result) { //for some reason curl returns CURLE_OK for a 404... case CURLE_HTTP_RETURNED_ERROR: case CURLE_OK: curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); if (result == CURLE_OK && response == 200) { //success break; } err = http_strerror(response); //404 is non-fatal if (response == 404) { level = PRINT_ALL; goto fail1; } //every other code is treated as fatal //not marking download as done since //we are falling back to UDP level = PRINT_ERROR; fatal_error = qtrue; goto fail2; case CURLE_COULDNT_RESOLVE_HOST: case CURLE_COULDNT_CONNECT: case CURLE_COULDNT_RESOLVE_PROXY: //connection problems are fatal err = curl_easy_strerror(result); level = PRINT_ERROR; fatal_error = qtrue; goto fail2; default: err = curl_easy_strerror(result); level = PRINT_WARNING; fail1: //we mark download as done even if it errored //to prevent multiple attempts. CL_FinishDownload(dl->queue); fail2: Com_LPrintf(level, "[HTTP] %s [%s] [%d remaining file%s]\n", dl->queue->path, err, cls.download.pending, cls.download.pending == 1 ? "" : "s"); if (dl->path[0]) { remove(dl->path); dl->path[0] = 0; } if (dl->buffer) { Z_Free(dl->buffer); dl->buffer = NULL; } curl_multi_remove_handle(curl_multi, curl); continue; } //mark as done CL_FinishDownload(dl->queue); //show some stats curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &sec); curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &bytes); if (sec < 0.001) sec = 0.001; Com_FormatSizeLong(size, sizeof(size), bytes); Com_FormatSizeLong(speed, sizeof(speed), bytes / sec); //FIXME: //technically i shouldn't need to do this as curl will auto reuse the //existing handle when you change the url. however, the curl_handles goes //all weird when reusing a download slot in this way. if you can figure //out why, please let me know. curl_multi_remove_handle(curl_multi, curl); Com_Printf("[HTTP] %s [%s, %s/sec] [%d remaining file%s]\n", dl->queue->path, size, speed, cls.download.pending, cls.download.pending == 1 ? "" : "s"); if (dl->path[0]) { //rename the temp file Q_snprintf(temp, sizeof(temp), "%s/%s", fs_gamedir, dl->queue->path); if (rename(dl->path, temp)) Com_EPrintf("[HTTP] Failed to rename '%s' to '%s': %s\n", dl->path, dl->queue->path, strerror(errno)); dl->path[0] = 0; //a pak file is very special... if (dl->queue->type == DL_PAK) { CL_RestartFilesystem(qfalse); rescan_queue(); } } else if (!fatal_error) { parse_file_list(dl); } } while (msgs_in_queue > 0); //fatal error occured, disable HTTP if (fatal_error) { abort_downloads(); return qfalse; } // see if we have more to dl CL_RequestNextDownload(); return qtrue; }
static void ReportLastError(const char *what) { Com_EPrintf("%s failed with error %lu\n", what, GetLastError()); }
static void Sys_InstallService_f(void) { char servicePath[256]; char serviceName[1024]; SC_HANDLE scm, service; DWORD error, length; char *commandline; if (Cmd_Argc() < 3) { Com_Printf("Usage: %s <servicename> <+command> [...]\n" "Example: %s test +set net_port 27910 +map q2dm1\n", Cmd_Argv(0), Cmd_Argv(0)); return; } scm = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); if (!scm) { error = GetLastError(); if (error == ERROR_ACCESS_DENIED) { Com_Printf("Insufficient privileges for opening Service Control Manager.\n"); } else { Com_EPrintf("%#lx opening Service Control Manager.\n", error); } return; } Q_concat(serviceName, sizeof(serviceName), "Q2PRO - ", Cmd_Argv(1), NULL); length = GetModuleFileName(NULL, servicePath, MAX_PATH); if (!length) { error = GetLastError(); Com_EPrintf("%#lx getting module file name.\n", error); goto fail; } commandline = Cmd_RawArgsFrom(2); if (length + strlen(commandline) + 10 > sizeof(servicePath) - 1) { Com_Printf("Oversize service command line.\n"); goto fail; } strcpy(servicePath + length, " -service "); strcpy(servicePath + length + 10, commandline); service = CreateService( scm, serviceName, serviceName, SERVICE_START, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, servicePath, NULL, NULL, NULL, NULL, NULL); if (!service) { error = GetLastError(); if (error == ERROR_SERVICE_EXISTS || error == ERROR_DUPLICATE_SERVICE_NAME) { Com_Printf("Service already exists.\n"); } else { Com_EPrintf("%#lx creating service.\n", error); } goto fail; } Com_Printf("Service created successfully.\n"); CloseServiceHandle(service); fail: CloseServiceHandle(scm); }
// Actually starts a download by adding it to the curl multi handle. static void start_download(dlqueue_t *entry, dlhandle_t *dl) { size_t len; char temp[MAX_QPATH]; char escaped[MAX_QPATH * 4]; CURLMcode ret; qerror_t err; //yet another hack to accomodate filelists, how i wish i could push :( //NULL file handle indicates filelist. if (entry->type == DL_LIST) { dl->file = NULL; dl->path[0] = 0; //filelist paths are absolute escape_path(entry->path, escaped); } else { len = Q_snprintf(dl->path, sizeof(dl->path), "%s/%s.tmp", fs_gamedir, entry->path); if (len >= sizeof(dl->path)) { Com_EPrintf("[HTTP] Refusing oversize temporary file path.\n"); goto fail; } //prepend quake path with gamedir len = Q_snprintf(temp, sizeof(temp), "%s/%s", http_gamedir(), entry->path); if (len >= sizeof(temp)) { Com_EPrintf("[HTTP] Refusing oversize server file path.\n"); goto fail; } escape_path(temp, escaped); err = FS_CreatePath(dl->path); if (err < 0) { Com_EPrintf("[HTTP] Couldn't create path to '%s': %s\n", dl->path, Q_ErrorString(err)); goto fail; } //don't bother with http resume... too annoying if server doesn't support it. dl->file = fopen(dl->path, "wb"); if (!dl->file) { Com_EPrintf("[HTTP] Couldn't open '%s' for writing: %s\n", dl->path, strerror(errno)); goto fail; } } len = Q_snprintf(dl->url, sizeof(dl->url), "%s%s", download_server, escaped); if (len >= sizeof(dl->url)) { Com_EPrintf("[HTTP] Refusing oversize download URL.\n"); goto fail; } dl->buffer = NULL; dl->size = 0; dl->position = 0; dl->queue = entry; if (!dl->curl) dl->curl = curl_easy_init(); curl_easy_setopt(dl->curl, CURLOPT_ENCODING, ""); #ifdef _DEBUG if (cl_http_debug->integer) { curl_easy_setopt(dl->curl, CURLOPT_DEBUGFUNCTION, debug_func); curl_easy_setopt(dl->curl, CURLOPT_VERBOSE, 1); } #endif curl_easy_setopt(dl->curl, CURLOPT_NOPROGRESS, 0); if (dl->file) { curl_easy_setopt(dl->curl, CURLOPT_WRITEDATA, dl->file); curl_easy_setopt(dl->curl, CURLOPT_WRITEFUNCTION, NULL); } else { curl_easy_setopt(dl->curl, CURLOPT_WRITEDATA, dl); curl_easy_setopt(dl->curl, CURLOPT_WRITEFUNCTION, recv_func); } curl_easy_setopt(dl->curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt(dl->curl, CURLOPT_PROXY, cl_http_proxy->string); curl_easy_setopt(dl->curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(dl->curl, CURLOPT_MAXREDIRS, 5); curl_easy_setopt(dl->curl, CURLOPT_PROGRESSFUNCTION, progress_func); curl_easy_setopt(dl->curl, CURLOPT_PROGRESSDATA, dl); curl_easy_setopt(dl->curl, CURLOPT_USERAGENT, com_version->string); curl_easy_setopt(dl->curl, CURLOPT_REFERER, download_referer); curl_easy_setopt(dl->curl, CURLOPT_URL, dl->url); ret = curl_multi_add_handle(curl_multi, dl->curl); if (ret != CURLM_OK) { Com_EPrintf("[HTTP] Failed to add download handle: %s\n", curl_multi_strerror(ret)); fail: CL_FinishDownload(entry); // see if we have more to dl CL_RequestNextDownload(); return; } Com_DPrintf("[HTTP] Fetching %s...\n", dl->url); entry->state = DL_RUNNING; curl_handles++; }