Exemple #1
0
PUBLIC HttpUri *httpCloneUri(HttpUri *base, int flags)
{
    HttpUri     *up;
    char        *path, *cp, *tok;

    if ((up = mprAllocObj(HttpUri, manageUri)) == 0) {
        up->valid = 0;
        return 0;
    }
    if (!base || !base->valid) {
        up->valid = 0;
        return up;
    }
    if (base->scheme) {
        up->scheme = sclone(base->scheme);
    } else if (flags & HTTP_COMPLETE_URI) {
        up->scheme = sclone("http");
    }
    up->secure = (smatch(up->scheme, "https") || smatch(up->scheme, "wss"));
    up->webSockets = (smatch(up->scheme, "ws") || smatch(up->scheme, "wss"));
    if (base->host) {
        up->host = sclone(base->host);
    } else if (flags & HTTP_COMPLETE_URI) {
        up->host = sclone("localhost");
    }
    if (base->port) {
        up->port = base->port;
    } else if (flags & HTTP_COMPLETE_URI) {
        up->port = up->secure ? 443 : 80;
    }
    path = base->path;
    if (path) {
        while (path[0] == '/' && path[1] == '/') {
            path++;
        }
        up->path = sclone(path);
    }
    if (flags & (HTTP_COMPLETE_URI | HTTP_COMPLETE_URI_PATH)) {
        if (up->path == 0 || *up->path == '\0') {
            up->path = sclone("/");
        }
    }
    if (base->reference) {
        up->reference = sclone(base->reference);
    }
    if (base->query) {
        up->query = sclone(base->query);
    }
    if (up->path && (tok = srchr(up->path, '.')) != 0) {
        if ((cp = srchr(up->path, '/')) != 0) {
            if (cp <= tok) {
                up->ext = sclone(&tok[1]);
            }
        } else {
            up->ext = sclone(&tok[1]);
        }
    }
    up->valid = 1;
    return up;
}
Exemple #2
0
BOOL   STDCALL OSGetLoadedModuleList(HANDLE hProcess, StringList &ModuleList)
{
    HMODULE hMods[1024];
    DWORD count;

    if (EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &count, LIST_MODULES_ALL))
    {
        for (UINT i=0; i<(count / sizeof(HMODULE)); i++)
        {
            TCHAR szFileName[MAX_PATH];

            if (GetModuleFileNameEx(hProcess, hMods[i], szFileName, _countof(szFileName)-1))
            {
                TCHAR *p;
                p = srchr(szFileName, '\\');
                if (p)
                {
                    *p = 0;
                    p++;
                }

                slwr (p);
                ModuleList << p;
            }
        }
    }
    else
        return 0;

    return 1;
}
Exemple #3
0
String GetPathExtension(CTSTR lpPath)
{
    assert(lpPath);
    if(!lpPath)
        return String();

    TSTR lpExtensionStart = srchr(lpPath, '.');
    if(lpExtensionStart)
        return String(lpExtensionStart+1);
    else
        return String();
}
Exemple #4
0
String GetPathFileName(CTSTR lpPath, BOOL bExtension)
{
    assert(lpPath);
    if(!lpPath)
        return String();

    OSFindData ofd;
    HANDLE hFind = OSFindFirstFile(lpPath, ofd);

    if(!hFind)
        ofd.bDirectory = FALSE;
    else
        OSFindClose(hFind);

    if(!ofd.bDirectory)
    {
        CTSTR lpDirectoryEnd = srchr(lpPath, '/');

        if(!lpDirectoryEnd)
            lpDirectoryEnd = srchr(lpPath, '/');

        if(lpDirectoryEnd)
            lpPath = lpDirectoryEnd+1;
    }

    String newPath = lpPath;
    if(newPath.IsValid())
    {
        if(!bExtension)
        {
            TSTR pDot = srchr(newPath, '.');
            if(pDot)
                newPath.SetLength((int)((((UPARAM)pDot)-((UPARAM)newPath.Array()))/sizeof(TCHAR)));
        }
    }

    return newPath;
}
Exemple #5
0
String GetPathDirectory(CTSTR lpPath)
{
    assert(lpPath);
    if(!lpPath)
        return String();

    OSFindData ofd;
    HANDLE hFind = OSFindFirstFile(lpPath, ofd);

    if(!hFind)
        ofd.bDirectory = FALSE;
    else
        OSFindClose(hFind);

    int nDirectoryEnd;

    if(!ofd.bDirectory)
    {
        CTSTR lpDirectoryEnd = srchr(lpPath, '/');

        if(!lpDirectoryEnd)
            lpDirectoryEnd = srchr(lpPath, '/');

        if(lpDirectoryEnd)
            nDirectoryEnd = (int)((((UPARAM)lpDirectoryEnd)-((UPARAM)lpPath))/sizeof(TCHAR));
        else
            nDirectoryEnd = slen(lpPath);
    }
    else
        nDirectoryEnd = slen(lpPath);

    String newPath = lpPath;

    newPath.SetLength(nDirectoryEnd);
    return newPath;
}
Exemple #6
0
String GetPathWithoutExtension(CTSTR lpPath)
{
    assert(lpPath);
    if(!lpPath)
        return String();

    TSTR lpExtensionStart = srchr(lpPath, '.');
    if(lpExtensionStart)
    {
        UINT newLength = (UINT)(UPARAM)(lpExtensionStart-lpPath);
        if(!newLength)
            return String();

        String newString;
        newString.SetLength(newLength);
        scpy_n(newString, lpPath, newLength);

        return newString;
    }
    else
        return String(lpPath);
}
Exemple #7
0
static void trimPathToDirname(HttpUri *uri) 
{
    char        *path, *cp;
    int         len;

    path = uri->path;
    len = (int) slen(path);
    if (path[len - 1] == '/') {
        if (len > 1) {
            path[len - 1] = '\0';
        }
    } else {
        if ((cp = srchr(path, '/')) != 0) {
            if (cp > path) {
                *cp = '\0';
            } else {
                cp[1] = '\0';
            }
        } else if (*path) {
            path[0] = '\0';
        }
    }
}
Exemple #8
0
String HTTPGetString (CTSTR url, CTSTR extraHeaders, int *responseCode, String verb)
{
    HINTERNET hSession = NULL;
    HINTERNET hConnect = NULL;
    HINTERNET hRequest = NULL;
    URL_COMPONENTS  urlComponents;
    BOOL secure = FALSE;
	String result = "";
	String body = TEXT("");
	String nurl = url;

    String hostName, path;

    const TCHAR *acceptTypes[] = {
        TEXT("*/*"),
        NULL
    };

	if (verb == TEXT("POST")){
		CTSTR s = srchr(url, TEXT('?'));
		body = String(s + 1);
		nurl = nurl.Left(s - url);
	}

    hostName.SetLength(256);
    path.SetLength(1024);

    zero(&urlComponents, sizeof(urlComponents));

    urlComponents.dwStructSize = sizeof(urlComponents);
    
    urlComponents.lpszHostName = hostName;
    urlComponents.dwHostNameLength = hostName.Length();

    urlComponents.lpszUrlPath = path;
    urlComponents.dwUrlPathLength = path.Length();

	WinHttpCrackUrl(nurl, 0, 0, &urlComponents);

    if (urlComponents.nPort == 443)
        secure = TRUE;

    hSession = WinHttpOpen(TEXT("gecko test"), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
    if (!hSession)
        goto failure;

    hConnect = WinHttpConnect(hSession, hostName, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0);
    if (!hConnect)
        goto failure;

    hRequest = WinHttpOpenRequest(hConnect, verb, path, NULL, WINHTTP_NO_REFERER, acceptTypes, secure ? WINHTTP_FLAG_SECURE|WINHTTP_FLAG_REFRESH : WINHTTP_FLAG_REFRESH);
    if (!hRequest)
        goto failure;

    BOOL bResults = WinHttpSendRequest(hRequest, extraHeaders, extraHeaders ? -1 : 0, body.Array(), 
		body.Length(), body.Length(), 0);

    // End the request.
    if (bResults)
        bResults = WinHttpReceiveResponse(hRequest, NULL);
    else
        goto failure;

    TCHAR statusCode[8];
    DWORD statusCodeLen;

    statusCodeLen = sizeof(statusCode);
    if (!WinHttpQueryHeaders (hRequest, WINHTTP_QUERY_STATUS_CODE, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeLen, WINHTTP_NO_HEADER_INDEX))
        goto failure;

    *responseCode = wcstoul(statusCode, NULL, 10);	

    if (bResults && *responseCode == 200)
    {
        CHAR buffer[16384];
        DWORD dwSize, dwOutSize;

        do 
        {
            // Check for available data.
            dwSize = 0;
            if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
                goto failure;

            if (!WinHttpReadData(hRequest, (LPVOID)buffer, dwSize, &dwOutSize))
            {
                goto failure;
            }
            else
            {
                if (!dwOutSize)
                    break;

				// Ensure the string is terminated.
				buffer[dwOutSize] = 0;

				String b = String((LPCSTR)buffer);
				result.AppendString(b);
            }
        } while (dwSize > 0);
    }

failure:
    if (hSession)
        WinHttpCloseHandle(hSession);
    if (hConnect)
        WinHttpCloseHandle(hConnect);
    if (hRequest)
        WinHttpCloseHandle(hRequest);

    return result;
}
static bool inRange(MprVersion *vp, cchar *expr)
{
    char    *cp, *ver, *op, *base, *pre, *all;
    cchar   *high, *low;
    uint64  factor, min, max, num;

    while (isspace((uchar) *expr)) expr++;

    if (srmatch(expr, semExpr, &all, &op, &ver, NULL) <= 0) {
        mprLog("error", 5, "Bad version expression: %s", expr);
        return 0;
    }
    if (smatch(op, "~")) {
        /*
            ~VER   Compatible with VER at the level of specificity given.
                   ~1.2.3 == (>=1.2.3 <1.3.0) Compatible at the patch level
                   ~1.2 == 1.2.x   Compatible at the minor level
                   ~1 == 1.x   Compatible at the major level
         */
        if (partCount(ver) == 3 && (cp = srchr(ver, '.')) != 0) {
            high = sjoin(snclone(ver, cp - ver), ".", MAX_VER_STR, NULL);
            if ((cp = schr(ver, '-')) != 0) {
                high = sjoin(high, cp, NULL);
            }
            return inRange(vp, sjoin(">=", ver, NULL)) &&
                   inRange(vp, sjoin("<", high, NULL));
        }
        return inRange(vp, completeVersion(ver, "x"));
    } 
    if (smatch(op, "^")) {
        /*
            ^VER  Compatible with VER at the most significant level.
                  ^0.2.3 == 0.2.3 <= VER < 0.3.0
                  ^1.2.3 == 1.2.3 <= VER < 2.0.0
            So convert to a range
         */
        high = ver;
        for (cp = ver, factor = VER_FACTOR * VER_FACTOR; *cp; cp++) {
            if (*cp == '.') {
                factor /= VER_FACTOR;
            } else if (isdigit((uchar) *cp) && *cp != '0') {
                num = (stoi(cp) + 1) * factor;
                high = numberToVersion(num);
                if ((cp = schr(ver, '-')) != 0) {
                    high = sjoin(high, cp, NULL);
                }
                break;
            }
        }
        return inRange(vp, sjoin(">=", ver, NULL)) && inRange(vp, sjoin("<", high, NULL));
    }
    ver = completeVersion(ver, "x");
    if (srmatch(ver, semCriteria, &all, &base, &pre, NULL) <= 0) {
        mprLog("error", 5, "Cannot match version %s", ver);
        return 0;
    }
    if (vp->preVersion) {
        if (!pre) {
            return 0;
        }
        if (snumber(vp->preVersion)) {
            if (stoi(pre) < stoi(vp->preVersion)) {
                return 0;
            }
        } else {
            if (scmp(pre, vp->preVersion) < 0 && !smatch(pre, "-")) {
                return 0;
            }
        }
    }
    min = 0;
    max = MAX_VER * VER_FACTOR * VER_FACTOR;
    if (schr(ver, 'x')) {
        if (smatch(op, ">=")) {
            // 1.2.3 >= 2.x.x ... 1.2.3 >= 2.0.0
            low = sreplace(ver, "x", "0");
            min = versionToNumber(low);
        } else if (smatch(op, "<=")) {
            // 1.2.3 < 2.x.x ... 1.2.3 <2.MAX.MAX
            high = sreplace(ver, "x", MAX_VER_STR);
            max = versionToNumber(high);
        } else if (*op == '>') {
            // 1.2.3 > 2.x.x ... 1.2.3 > 2.0.0
            low = sreplace(ver, "x", "0");
            min = versionToNumber(low) + 1;
        } else if (*op == '<') {
            // 1.2.3 < 2.x.x ... 1.2.3 <2.MAX.MAX
            high = sreplace(ver, "x", MAX_VER_STR);
            max = versionToNumber(high) - 1;
        } else {
            low = sreplace(ver, "x", "0");
            high = sreplace(ver, "x", MAX_VER_STR);
            return inRange(vp, sjoin(">=", low, NULL)) && inRange(vp, sjoin("<", high, NULL));
        }
    } else if (smatch(op, ">=")) {
        min = versionToNumber(base);
    } else if (smatch(op, "<=")) {
        max = versionToNumber(base);
    } else if (*op == '>') {
        min = versionToNumber(base) + 1;
    } else if (*op == '<') {
        max = versionToNumber(base) - 1;
    } else {
        min = max = versionToNumber(base);
    }
    if (min <= vp->numberVersion && vp->numberVersion <= max) {
        return 1;
    }
    return 0;
}
Exemple #10
0
LONG CALLBACK OBSExceptionHandler (PEXCEPTION_POINTERS exceptionInfo)
{
    HANDLE  hProcess;

    HMODULE hDbgHelp;

    MINIDUMP_EXCEPTION_INFORMATION miniInfo;

    STACKFRAME64        frame = {0};
    CONTEXT             context = *exceptionInfo->ContextRecord;
    SYMBOL_INFO         *symInfo;
    DWORD64             fnOffset;
    TCHAR               logPath[MAX_PATH];

    OSVERSIONINFOEX     osInfo;
    SYSTEMTIME          timeInfo;

    ENUMERATELOADEDMODULES64    fnEnumerateLoadedModules64;
    SYMSETOPTIONS               fnSymSetOptions;
    SYMINITIALIZE               fnSymInitialize;
    STACKWALK64                 fnStackWalk64;
    SYMFUNCTIONTABLEACCESS64    fnSymFunctionTableAccess64;
    SYMGETMODULEBASE64          fnSymGetModuleBase64;
    SYMFROMADDR                 fnSymFromAddr;
    SYMCLEANUP                  fnSymCleanup;
    MINIDUMPWRITEDUMP           fnMiniDumpWriteDump;
    SYMGETMODULEINFO64          fnSymGetModuleInfo64;

    DWORD                       i;
    DWORD64                     InstructionPtr;
    DWORD                       imageType;

    TCHAR                       searchPath[MAX_PATH], *p;

    static BOOL                 inExceptionHandler = FALSE;

    moduleinfo_t                moduleInfo;

    //always break into a debugger if one is present
    if (IsDebuggerPresent ())
        return EXCEPTION_CONTINUE_SEARCH;

    //exception codes < 0x80000000 are typically informative only and not crash worthy
    //0xe06d7363 indicates a c++ exception was thrown, let's just hope it was caught.
    //this is no longer needed since we're an unhandled handler vs a vectored handler
    
    /*if (exceptionInfo->ExceptionRecord->ExceptionCode < 0x80000000 || exceptionInfo->ExceptionRecord->ExceptionCode == 0xe06d7363 ||
        exceptionInfo->ExceptionRecord->ExceptionCode == 0x800706b5)
        return EXCEPTION_CONTINUE_SEARCH;*/

    //uh oh, we're crashing inside ourselves... this is really bad!
    if (inExceptionHandler)
        return EXCEPTION_CONTINUE_SEARCH;

    inExceptionHandler = TRUE;

    //load dbghelp dynamically
    hDbgHelp = LoadLibrary (TEXT("DBGHELP"));

    if (!hDbgHelp)
        return EXCEPTION_CONTINUE_SEARCH;

    fnEnumerateLoadedModules64 = (ENUMERATELOADEDMODULES64)GetProcAddress (hDbgHelp, "EnumerateLoadedModulesW64");
    fnSymSetOptions = (SYMSETOPTIONS)GetProcAddress (hDbgHelp, "SymSetOptions");
    fnSymInitialize = (SYMINITIALIZE)GetProcAddress (hDbgHelp, "SymInitialize");
    fnSymFunctionTableAccess64 = (SYMFUNCTIONTABLEACCESS64)GetProcAddress (hDbgHelp, "SymFunctionTableAccess64");
    fnSymGetModuleBase64 = (SYMGETMODULEBASE64)GetProcAddress (hDbgHelp, "SymGetModuleBase64");
    fnStackWalk64 = (STACKWALK64)GetProcAddress (hDbgHelp, "StackWalk64");
    fnSymFromAddr = (SYMFROMADDR)GetProcAddress (hDbgHelp, "SymFromAddrW");
    fnSymCleanup = (SYMCLEANUP)GetProcAddress (hDbgHelp, "SymCleanup");
    fnSymGetModuleInfo64 = (SYMGETMODULEINFO64)GetProcAddress (hDbgHelp, "SymGetModuleInfo64");
    fnMiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress (hDbgHelp, "MiniDumpWriteDump");

    if (!fnEnumerateLoadedModules64 || !fnSymSetOptions || !fnSymInitialize || !fnSymFunctionTableAccess64 ||
        !fnSymGetModuleBase64 || !fnStackWalk64 || !fnSymFromAddr || !fnSymCleanup || !fnSymGetModuleInfo64)
    {
        FreeLibrary (hDbgHelp);
        return EXCEPTION_CONTINUE_SEARCH;
    }

    hProcess = GetCurrentProcess();

    fnSymSetOptions (SYMOPT_UNDNAME | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_LOAD_ANYTHING);

    GetModuleFileName (NULL, searchPath, _countof(searchPath)-1);
    p = srchr (searchPath, '\\');
    if (p)
        *p = 0;

    //create a log file
    GetSystemTime (&timeInfo);
    for (i = 1;;)
    {
        tsprintf_s (logPath, _countof(logPath)-1, TEXT("%s\\crashDumps\\OBSCrashLog%.4d-%.2d-%.2d_%d.txt"), lpAppDataPath, timeInfo.wYear, timeInfo.wMonth, timeInfo.wDay, i);
        if (GetFileAttributes(logPath) == INVALID_FILE_ATTRIBUTES)
            break;
        i++;
    }

    XFile   crashDumpLog;

    if (!crashDumpLog.Open(logPath, XFILE_WRITE, XFILE_CREATENEW))
    {
        FreeLibrary (hDbgHelp);
        return EXCEPTION_CONTINUE_SEARCH;
    }

    //initialize debug symbols
    fnSymInitialize (hProcess, NULL, TRUE);

#ifdef _WIN64
    InstructionPtr = context.Rip;
    frame.AddrPC.Offset = InstructionPtr;
    frame.AddrFrame.Offset = context.Rbp;
    frame.AddrStack.Offset = context.Rsp;
    imageType = IMAGE_FILE_MACHINE_AMD64;
#else
    InstructionPtr = context.Eip;
    frame.AddrPC.Offset = InstructionPtr;
    frame.AddrFrame.Offset = context.Ebp;
    frame.AddrStack.Offset = context.Esp;
    imageType = IMAGE_FILE_MACHINE_I386;
#endif

    frame.AddrFrame.Mode = AddrModeFlat;
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrStack.Mode = AddrModeFlat;

    symInfo = (SYMBOL_INFO *)LocalAlloc (LPTR, sizeof(*symInfo) + 256);
    symInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
    symInfo->MaxNameLen = 256;
    fnOffset = 0;

    //get os info
    memset (&osInfo, 0, sizeof(osInfo));
    osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

    if (!GetVersionEx ((OSVERSIONINFO *)&osInfo))
    {
        osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        GetVersionEx ((OSVERSIONINFO *)&osInfo);
    }

    String cpuInfo;
    HKEY key;

    // get cpu info
    if(RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), &key) == ERROR_SUCCESS)
    {
        DWORD dwSize = 1024;
        cpuInfo.SetLength(dwSize);
        if (RegQueryValueEx(key, TEXT("ProcessorNameString"), NULL, NULL, (LPBYTE)cpuInfo.Array(), &dwSize) != ERROR_SUCCESS)
            cpuInfo = TEXT("<unable to query>");
        RegCloseKey(key);
    }
    else
        cpuInfo = TEXT("<unable to query>");

    //determine which module the crash occured in
    scpy (moduleInfo.moduleName, TEXT("<unknown>"));
    moduleInfo.faultAddress = InstructionPtr;
    fnEnumerateLoadedModules64 (hProcess, (PENUMLOADED_MODULES_CALLBACK64)EnumerateLoadedModulesProcInfo, (VOID *)&moduleInfo);
    slwr (moduleInfo.moduleName);

    BOOL isPlugin = FALSE;

    if (sstr (moduleInfo.moduleName, TEXT("plugins\\")))
        isPlugin = TRUE;

    String strModuleInfo;
    String crashMessage;

    fnEnumerateLoadedModules64(hProcess, (PENUMLOADED_MODULES_CALLBACK64)RecordAllLoadedModules, (VOID *)&strModuleInfo);

    crashMessage << 
        TEXT("OBS has encountered an unhandled exception and has terminated. If you are able to\r\n")
        TEXT("reproduce this crash, please submit this crash report on the forums at\r\n")
        TEXT("http://www.obsproject.com/ - include the contents of this crash log and the\r\n")
        TEXT("minidump .dmp file (if available) as well as your regular OBS log files and\r\n")
        TEXT("a description of what you were doing at the time of the crash.\r\n")
        TEXT("\r\n")
        TEXT("This crash appears to have occured in the '") << moduleInfo.moduleName << TEXT("' module.\r\n\r\n");

    crashDumpLog.WriteStr(crashMessage.Array());

    crashDumpLog.WriteStr(FormattedString(TEXT("**** UNHANDLED EXCEPTION: %x\r\nFault address: %I64p (%s)\r\n"), exceptionInfo->ExceptionRecord->ExceptionCode, InstructionPtr, moduleInfo.moduleName));

    crashDumpLog.WriteStr(TEXT("OBS version: ") OBS_VERSION_STRING TEXT("\r\n"));
    crashDumpLog.WriteStr(FormattedString(TEXT("Windows version: %d.%d (Build %d) %s\r\nCPU: %s\r\n\r\n"), osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.dwBuildNumber, osInfo.szCSDVersion, cpuInfo.Array()));

    crashDumpLog.WriteStr(TEXT("Crashing thread stack trace:\r\n"));
#ifdef _WIN64
    crashDumpLog.WriteStr(TEXT("Stack            EIP              Arg0             Arg1             Arg2             Arg3             Address\r\n"));
#else
    crashDumpLog.WriteStr(TEXT("Stack    EIP      Arg0     Arg1     Arg2     Arg3     Address\r\n"));
#endif
    crashDumpLog.FlushFileBuffers();

    while (fnStackWalk64 (imageType, hProcess, GetCurrentThread(), &frame, &context, NULL, (PFUNCTION_TABLE_ACCESS_ROUTINE64)fnSymFunctionTableAccess64, (PGET_MODULE_BASE_ROUTINE64)fnSymGetModuleBase64, NULL))
    {
        scpy (moduleInfo.moduleName, TEXT("<unknown>"));
        moduleInfo.faultAddress = frame.AddrPC.Offset;
        fnEnumerateLoadedModules64 (hProcess, (PENUMLOADED_MODULES_CALLBACK64)EnumerateLoadedModulesProcInfo, (VOID *)&moduleInfo);
        slwr (moduleInfo.moduleName);

        p = srchr (moduleInfo.moduleName, '\\');
        if (p)
            p++;
        else
            p = moduleInfo.moduleName;

#ifdef _WIN64
        if (fnSymFromAddr (hProcess, frame.AddrPC.Offset, &fnOffset, symInfo) && !(symInfo->Flags & SYMFLAG_EXPORT))
        {
            crashDumpLog.WriteStr(FormattedString(TEXT("%016I64X %016I64X %016I64X %016I64X %016I64X %016I64X %s!%s+0x%I64x\r\n"),
                frame.AddrStack.Offset,
                frame.AddrPC.Offset,
                frame.Params[0],
                frame.Params[1],
                frame.Params[2],
                frame.Params[3],
                p,
                symInfo->Name,
                fnOffset));
        }
        else
        {
            crashDumpLog.WriteStr(FormattedString(TEXT("%016I64X %016I64X %016I64X %016I64X %016I64X %016I64X %s!0x%I64x\r\n"),
                frame.AddrStack.Offset,
                frame.AddrPC.Offset,
                frame.Params[0],
                frame.Params[1],
                frame.Params[2],
                frame.Params[3],
                p,
                frame.AddrPC.Offset));
        }
#else
        if (fnSymFromAddr (hProcess, frame.AddrPC.Offset, &fnOffset, symInfo) && !(symInfo->Flags & SYMFLAG_EXPORT))
        {
            crashDumpLog.WriteStr(FormattedString(TEXT("%08.8I64X %08.8I64X %08.8X %08.8X %08.8X %08.8X %s!%s+0x%I64x\r\n"),
                frame.AddrStack.Offset,
                frame.AddrPC.Offset,
                (DWORD)frame.Params[0],
                (DWORD)frame.Params[1],
                (DWORD)frame.Params[2],
                (DWORD)frame.Params[3],
                p,
                symInfo->Name,
                fnOffset));
        }
        else
        {
            crashDumpLog.WriteStr(FormattedString(TEXT("%08.8I64X %08.8I64X %08.8X %08.8X %08.8X %08.8X %s!0x%I64x\r\n"),
                frame.AddrStack.Offset,
                frame.AddrPC.Offset,
                (DWORD)frame.Params[0],
                (DWORD)frame.Params[1],
                (DWORD)frame.Params[2],
                (DWORD)frame.Params[3],
                p,
                frame.AddrPC.Offset
                ));
        }
#endif

        crashDumpLog.FlushFileBuffers();
    }

    //if we manually crashed due to a deadlocked thread, record some extra info
    if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
    {
        HANDLE hVideoThread = NULL, hEncodeThread = NULL;
        App->GetThreadHandles (&hVideoThread, &hEncodeThread);

        if (hVideoThread)
        {
            crashDumpLog.WriteStr(TEXT("\r\nVideo thread stack trace:\r\n"));
#ifdef _WIN64
            crashDumpLog.WriteStr(TEXT("Stack            EIP              Arg0             Arg1             Arg2             Arg3             Address\r\n"));
#else
            crashDumpLog.WriteStr(TEXT("Stack    EIP      Arg0     Arg1     Arg2     Arg3     Address\r\n"));
#endif
            crashDumpLog.FlushFileBuffers();

            context.ContextFlags = CONTEXT_ALL;
            GetThreadContext (hVideoThread, &context);
            ZeroMemory (&frame, sizeof(frame));
#ifdef _WIN64
            InstructionPtr = context.Rip;
            frame.AddrPC.Offset = InstructionPtr;
            frame.AddrFrame.Offset = context.Rbp;
            frame.AddrStack.Offset = context.Rsp;
            imageType = IMAGE_FILE_MACHINE_AMD64;
#else
            InstructionPtr = context.Eip;
            frame.AddrPC.Offset = InstructionPtr;
            frame.AddrFrame.Offset = context.Ebp;
            frame.AddrStack.Offset = context.Esp;
            imageType = IMAGE_FILE_MACHINE_I386;
#endif

            frame.AddrFrame.Mode = AddrModeFlat;
            frame.AddrPC.Mode = AddrModeFlat;
            frame.AddrStack.Mode = AddrModeFlat;
            while (fnStackWalk64 (imageType, hProcess, hVideoThread, &frame, &context, NULL, (PFUNCTION_TABLE_ACCESS_ROUTINE64)fnSymFunctionTableAccess64, (PGET_MODULE_BASE_ROUTINE64)fnSymGetModuleBase64, NULL))
            {
                scpy (moduleInfo.moduleName, TEXT("<unknown>"));
                moduleInfo.faultAddress = frame.AddrPC.Offset;
                fnEnumerateLoadedModules64 (hProcess, (PENUMLOADED_MODULES_CALLBACK64)EnumerateLoadedModulesProcInfo, (VOID *)&moduleInfo);
                slwr (moduleInfo.moduleName);

                p = srchr (moduleInfo.moduleName, '\\');
                if (p)
                    p++;
                else
                    p = moduleInfo.moduleName;

#ifdef _WIN64
                if (fnSymFromAddr (hProcess, frame.AddrPC.Offset, &fnOffset, symInfo) && !(symInfo->Flags & SYMFLAG_EXPORT))
                {
                    crashDumpLog.WriteStr(FormattedString(TEXT("%016I64X %016I64X %016I64X %016I64X %016I64X %016I64X %s!%s+0x%I64x\r\n"),
                        frame.AddrStack.Offset,
                        frame.AddrPC.Offset,
                        frame.Params[0],
                        frame.Params[1],
                        frame.Params[2],
                        frame.Params[3],
                        p,
                        symInfo->Name,
                        fnOffset));
                }
                else
                {
                    crashDumpLog.WriteStr(FormattedString(TEXT("%016I64X %016I64X %016I64X %016I64X %016I64X %016I64X %s!0x%I64x\r\n"),
                        frame.AddrStack.Offset,
                        frame.AddrPC.Offset,
                        frame.Params[0],
                        frame.Params[1],
                        frame.Params[2],
                        frame.Params[3],
                        p,
                        frame.AddrPC.Offset));
                }
#else
                if (fnSymFromAddr (hProcess, frame.AddrPC.Offset, &fnOffset, symInfo) && !(symInfo->Flags & SYMFLAG_EXPORT))
                {
                    crashDumpLog.WriteStr(FormattedString(TEXT("%08.8I64X %08.8I64X %08.8X %08.8X %08.8X %08.8X %s!%s+0x%I64x\r\n"),
                        frame.AddrStack.Offset,
                        frame.AddrPC.Offset,
                        (DWORD)frame.Params[0],
                        (DWORD)frame.Params[1],
                        (DWORD)frame.Params[2],
                        (DWORD)frame.Params[3],
                        p,
                        symInfo->Name,
                        fnOffset));
                }
                else
                {
                    crashDumpLog.WriteStr(FormattedString(TEXT("%08.8I64X %08.8I64X %08.8X %08.8X %08.8X %08.8X %s!0x%I64x\r\n"),
                        frame.AddrStack.Offset,
                        frame.AddrPC.Offset,
                        (DWORD)frame.Params[0],
                        (DWORD)frame.Params[1],
                        (DWORD)frame.Params[2],
                        (DWORD)frame.Params[3],
                        p,
                        frame.AddrPC.Offset
                        ));
                }
#endif

                crashDumpLog.FlushFileBuffers();
            }
        }

        if (hEncodeThread)
        {
            crashDumpLog.WriteStr(TEXT("\r\nEncode thread stack trace:\r\n"));
#ifdef _WIN64
            crashDumpLog.WriteStr(TEXT("Stack            EIP              Arg0             Arg1             Arg2             Arg3             Address\r\n"));
#else
            crashDumpLog.WriteStr(TEXT("Stack    EIP      Arg0     Arg1     Arg2     Arg3     Address\r\n"));
#endif
            crashDumpLog.FlushFileBuffers();

            context.ContextFlags = CONTEXT_ALL;
            GetThreadContext (hEncodeThread, &context);
            ZeroMemory (&frame, sizeof(frame));
#ifdef _WIN64
            InstructionPtr = context.Rip;
            frame.AddrPC.Offset = InstructionPtr;
            frame.AddrFrame.Offset = context.Rbp;
            frame.AddrStack.Offset = context.Rsp;
            imageType = IMAGE_FILE_MACHINE_AMD64;
#else
            InstructionPtr = context.Eip;
            frame.AddrPC.Offset = InstructionPtr;
            frame.AddrFrame.Offset = context.Ebp;
            frame.AddrStack.Offset = context.Esp;
            imageType = IMAGE_FILE_MACHINE_I386;
#endif

            frame.AddrFrame.Mode = AddrModeFlat;
            frame.AddrPC.Mode = AddrModeFlat;
            frame.AddrStack.Mode = AddrModeFlat;
            while (fnStackWalk64 (imageType, hProcess, hEncodeThread, &frame, &context, NULL, (PFUNCTION_TABLE_ACCESS_ROUTINE64)fnSymFunctionTableAccess64, (PGET_MODULE_BASE_ROUTINE64)fnSymGetModuleBase64, NULL))
            {
                scpy (moduleInfo.moduleName, TEXT("<unknown>"));
                moduleInfo.faultAddress = frame.AddrPC.Offset;
                fnEnumerateLoadedModules64 (hProcess, (PENUMLOADED_MODULES_CALLBACK64)EnumerateLoadedModulesProcInfo, (VOID *)&moduleInfo);
                slwr (moduleInfo.moduleName);

                p = srchr (moduleInfo.moduleName, '\\');
                if (p)
                    p++;
                else
                    p = moduleInfo.moduleName;

#ifdef _WIN64
                if (fnSymFromAddr (hProcess, frame.AddrPC.Offset, &fnOffset, symInfo) && !(symInfo->Flags & SYMFLAG_EXPORT))
                {
                    crashDumpLog.WriteStr(FormattedString(TEXT("%016I64X %016I64X %016I64X %016I64X %016I64X %016I64X %s!%s+0x%I64x\r\n"),
                        frame.AddrStack.Offset,
                        frame.AddrPC.Offset,
                        frame.Params[0],
                        frame.Params[1],
                        frame.Params[2],
                        frame.Params[3],
                        p,
                        symInfo->Name,
                        fnOffset));
                }
                else
                {
                    crashDumpLog.WriteStr(FormattedString(TEXT("%016I64X %016I64X %016I64X %016I64X %016I64X %016I64X %s!0x%I64x\r\n"),
                        frame.AddrStack.Offset,
                        frame.AddrPC.Offset,
                        frame.Params[0],
                        frame.Params[1],
                        frame.Params[2],
                        frame.Params[3],
                        p,
                        frame.AddrPC.Offset));
                }
#else
                if (fnSymFromAddr (hProcess, frame.AddrPC.Offset, &fnOffset, symInfo) && !(symInfo->Flags & SYMFLAG_EXPORT))
                {
                    crashDumpLog.WriteStr(FormattedString(TEXT("%08.8I64X %08.8I64X %08.8X %08.8X %08.8X %08.8X %s!%s+0x%I64x\r\n"),
                        frame.AddrStack.Offset,
                        frame.AddrPC.Offset,
                        (DWORD)frame.Params[0],
                        (DWORD)frame.Params[1],
                        (DWORD)frame.Params[2],
                        (DWORD)frame.Params[3],
                        p,
                        symInfo->Name,
                        fnOffset));
                }
                else
                {
                    crashDumpLog.WriteStr(FormattedString(TEXT("%08.8I64X %08.8I64X %08.8X %08.8X %08.8X %08.8X %s!0x%I64x\r\n"),
                        frame.AddrStack.Offset,
                        frame.AddrPC.Offset,
                        (DWORD)frame.Params[0],
                        (DWORD)frame.Params[1],
                        (DWORD)frame.Params[2],
                        (DWORD)frame.Params[3],
                        p,
                        frame.AddrPC.Offset
                        ));
                }
#endif

                crashDumpLog.FlushFileBuffers();
            }
        }

    }

    //generate a minidump if possible
    if (fnMiniDumpWriteDump)
    {
        TCHAR     dumpPath[MAX_PATH];
        HANDLE    hFile;

        tsprintf_s (dumpPath, _countof(dumpPath)-1, TEXT("%s\\crashDumps\\OBSCrashDump%.4d-%.2d-%.2d_%d.dmp"), lpAppDataPath, timeInfo.wYear, timeInfo.wMonth, timeInfo.wDay, i);

        hFile = CreateFile (dumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile != INVALID_HANDLE_VALUE)
        {
            MINIDUMP_TYPE dumpFlags = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData);

            miniInfo.ClientPointers = TRUE;
            miniInfo.ExceptionPointers = exceptionInfo;
            miniInfo.ThreadId = GetCurrentThreadId ();

            if (fnMiniDumpWriteDump (hProcess, GetCurrentProcessId(), hFile, dumpFlags, &miniInfo, NULL, NULL))
            {
                crashDumpLog.WriteStr(FormattedString(TEXT("\r\nA minidump was saved to %s.\r\nPlease include this file when posting a crash report.\r\n"), dumpPath));
            }
            else
            {
                CloseHandle (hFile);
                DeleteFile (dumpPath);
            }
        }
    }
    else
    {
        crashDumpLog.WriteStr(TEXT("\r\nA minidump could not be created. Please check dbghelp.dll is present.\r\n"));
    }

    crashDumpLog.WriteStr("\r\nList of loaded modules:\r\n");
#ifdef _WIN64
    crashDumpLog.WriteStr("Base Address                      Module\r\n");
#else
    crashDumpLog.WriteStr("Base Address      Module\r\n");
#endif
    crashDumpLog.WriteStr(strModuleInfo);

    crashDumpLog.Close();

    LocalFree (symInfo);

    fnSymCleanup (hProcess);

    if (OBSMessageBox(hwndMain, TEXT("Woops! OBS has crashed. Would you like to view a crash report?"), NULL, MB_ICONERROR | MB_YESNO) == IDYES)
        ShellExecute(NULL, NULL, logPath, NULL, searchPath, SW_SHOWDEFAULT);

    FreeLibrary (hDbgHelp);

    //we really shouldn't be returning here, if we're at the bottom of the VEH chain this is a pretty legitimate crash
    //and if we return we could end up invoking a second crash handler or other weird / annoying things
    //ExitProcess(exceptionInfo->ExceptionRecord->ExceptionCode);
    return EXCEPTION_CONTINUE_SEARCH;
}
Exemple #11
0
/*
    Create and initialize a URI. This accepts full URIs with schemes (http:) and partial URLs
    Support IPv4 and [IPv6]. Supported forms:

        SCHEME://[::]:PORT/URI
        SCHEME://HOST:PORT/URI
        [::]:PORT/URI
        :PORT/URI
        HOST:PORT/URI
        PORT/URI
        /URI
        URI

        NOTE: HOST/URI is not supported and requires a scheme prefix. This is because it is ambiguous with a 
        relative uri path.

    Missing fields are null or zero.
 */
PUBLIC HttpUri *httpCreateUri(cchar *uri, int flags)
{
    HttpUri     *up;
    char        *tok, *next;

    if ((up = mprAllocObj(HttpUri, manageUri)) == 0) {
        return 0;
    }
    tok = sclone(uri);

    /*
        [scheme://][hostname[:port]][/path[.ext]][#ref][?query]
        First trim query and then reference from the end
     */
    if ((next = schr(tok, '?')) != 0) {
        *next++ = '\0';
        up->query = sclone(next);
    }
    if ((next = schr(tok, '#')) != 0) {
        *next++ = '\0';
        up->reference = sclone(next);
    }

    /*
        [scheme://][hostname[:port]][/path]
     */
    if ((next = scontains(tok, "://")) != 0) {
        up->scheme = snclone(tok, (next - tok));
        if (smatch(up->scheme, "http")) {
            if (flags & HTTP_COMPLETE_URI) {
                up->port = 80;
            }
        } else if (smatch(up->scheme, "ws")) {
            if (flags & HTTP_COMPLETE_URI) {
                up->port = 80;
            }
            up->webSockets = 1;
        } else if (smatch(up->scheme, "https")) {
            if (flags & HTTP_COMPLETE_URI) {
                up->port = 443;
            }
            up->secure = 1;
        } else if (smatch(up->scheme, "wss")) {
            if (flags & HTTP_COMPLETE_URI) {
                up->port = 443;
            }
            up->secure = 1;
            up->webSockets = 1;
        }
        tok = &next[3];
    }

    /*
        [hostname[:port]][/path]
     */
    if (*tok == '[' && ((next = strchr(tok, ']')) != 0)) {
        /* IPv6  [::]:port/uri */
        up->host = snclone(&tok[1], (next - tok) - 1);
        tok = ++next;

    } else if (*tok && *tok != '/' && *tok != ':' && (up->scheme || strchr(tok, ':'))) {
        /*
            Supported forms:
                scheme://hostname
                hostname:port
         */
        if ((next = spbrk(tok, ":/")) == 0) {
            next = &tok[slen(tok)];
        }
        up->host = snclone(tok, next - tok);
        tok = next;
    }
    assert(tok);

    /* [:port][/path] */
    if (*tok == ':') {
        up->port = atoi(++tok);
        if ((tok = schr(tok, '/')) == 0) {
            tok = "";
        }
    }
    assert(tok);

    /* [/path] */
    if (*tok) {
        up->path = sclone(tok);
        /* path[.ext[/extra]] */
        if ((tok = srchr(up->path, '.')) != 0) {
            if (tok[1]) {
                if ((next = srchr(up->path, '/')) != 0) {
                    if (next < tok) {
                        up->ext = sclone(++tok);
                    }
                } else {
                    up->ext = sclone(++tok);
                }
            }
        }
    }
    if (flags & (HTTP_COMPLETE_URI | HTTP_COMPLETE_URI_PATH)) {
        if (up->path == 0 || *up->path == '\0') {
            up->path = sclone("/");
        }
    }
    up->secure = smatch(up->scheme, "https") || smatch(up->scheme, "wss");
    up->webSockets = (smatch(up->scheme, "ws") || smatch(up->scheme, "wss"));

    if (flags & HTTP_COMPLETE_URI) {
        if (!up->scheme) {
            up->scheme = sclone("http");
        }
        if (!up->host) {
            up->host = sclone("localhost");
        }
        if (!up->port) {
            up->port = up->secure ? 443 : 80;
        }
    }
    up->valid = httpValidUriChars(uri);
    return up;
}
Exemple #12
0
/*
    Create and initialize a URI. This accepts full URIs with schemes (http:) and partial URLs
 */
PUBLIC HttpUri *httpCreateUriFromParts(cchar *scheme, cchar *host, int port, cchar *path, cchar *reference, cchar *query, 
        int flags)
{
    HttpUri     *up;
    char        *cp, *tok;

    if ((up = mprAllocObj(HttpUri, manageUri)) == 0) {
        up->valid = 0;
        return 0;
    }
    if (!httpValidUriChars(scheme) || !httpValidUriChars(host) || !httpValidUriChars(path) ||
        !httpValidUriChars(reference) || !httpValidUriChars(query)) {
        up->valid = 0;
        return up;
    }
    if (scheme) {
        up->scheme = sclone(scheme);
        up->secure = (smatch(up->scheme, "https") || smatch(up->scheme, "wss"));
        up->webSockets = (smatch(up->scheme, "ws") || smatch(up->scheme, "wss"));

    } else if (flags & HTTP_COMPLETE_URI) {
        up->scheme = "http";
    }
    if (host) {
        if (*host == '[' && ((cp = strchr(host, ']')) != 0)) {
            up->host = snclone(&host[1], (cp - host) - 2);
            if ((cp = schr(++cp, ':')) && port == 0) {
                port = (int) stoi(++cp);
            }
        } else {
            up->host = sclone(host);
            if ((cp = schr(up->host, ':')) && port == 0) {
                port = (int) stoi(++cp);
            }
        }
    } else if (flags & HTTP_COMPLETE_URI) {
        up->host = sclone("localhost");
    }
    if (port) {
        up->port = port;
    }
    if (path) {
        while (path[0] == '/' && path[1] == '/') {
            path++;
        }
        up->path = sclone(path);
    }
    if (flags & (HTTP_COMPLETE_URI | HTTP_COMPLETE_URI_PATH)) {
        if (up->path == 0 || *up->path == '\0') {
            up->path = sclone("/");
        }
    }
    if (reference) {
        up->reference = sclone(reference);
    }
    if (query) {
        up->query = sclone(query);
    }
    if ((tok = srchr(up->path, '.')) != 0) {
        if ((cp = srchr(up->path, '/')) != 0) {
            if (cp <= tok) {
                up->ext = sclone(&tok[1]);
            }
        } else {
            up->ext = sclone(&tok[1]);
        }
    }
    up->valid = 1;
    return up;
}
Exemple #13
0
DWORD WINAPI CheckUpdateThread (VOID *arg)
{
    int responseCode;
    TCHAR extraHeaders[256];
    BYTE manifestHash[20];
    TCHAR manifestPath[MAX_PATH];

    tsprintf_s (manifestPath, _countof(manifestPath)-1, TEXT("%s\\updates\\packages.xconfig"), lpAppDataPath);

    if (!CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        Log (TEXT("Updater: CryptAcquireContext failed: %08x"), GetLastError());
        return 1;
    }

    extraHeaders[0] = 0;

    if (CalculateFileHash(manifestPath, manifestHash))
    {
        TCHAR hashString[41];

        HashToString(manifestHash, hashString);

        tsprintf_s (extraHeaders, _countof(extraHeaders)-1, TEXT("If-None-Match: %s"), hashString);
    }
    
    //this is an arbitrary random number that we use to count the number of unique OBS installations
    //and is not associated with any kind of identifiable information
    String strGUID = GlobalConfig->GetString(TEXT("General"), TEXT("InstallGUID"));
    if (strGUID.IsEmpty())
    {
        GenerateGUID(strGUID);

        if (strGUID.IsValid())
            GlobalConfig->SetString(TEXT("General"), TEXT("InstallGUID"), strGUID);
    }

    if (strGUID.IsValid())
    {
        if (extraHeaders[0])
            scat(extraHeaders, TEXT("\n"));

        scat(extraHeaders, TEXT("X-OBS-GUID: "));
        scat(extraHeaders, strGUID);
    }

    if (HTTPGetFile(TEXT("https://obsproject.com/update/packages.xconfig"), manifestPath, extraHeaders, &responseCode))
    {
        if (responseCode == 200 || responseCode == 304)
        {
            String updateInfo;
            BOOL updatesAvailable;

            updateInfo = Str("Updater.NewUpdates");

            if (ParseUpdateManifest(manifestPath, &updatesAvailable, updateInfo))
            {
                if (updatesAvailable)
                {
                    updateInfo << TEXT("\r\n") << Str("Updater.DownloadNow");

                    if (MessageBox (NULL, updateInfo.Array(), Str("Updater.UpdatesAvailable"), MB_ICONQUESTION|MB_YESNO) == IDYES)
                    {
                        if (App->IsRunning())
                        {
                            if (MessageBox (NULL, Str("Updater.RunningWarning"), NULL, MB_ICONEXCLAMATION|MB_YESNO) == IDNO)
                                goto abortUpdate;
                        }

                        TCHAR updateFilePath[MAX_PATH];
                        TCHAR cwd[MAX_PATH];

                        GetModuleFileName(NULL, cwd, _countof(cwd)-1);
                        TCHAR *p = srchr(cwd, '\\');
                        if (p)
                            *p = 0;

                        tsprintf_s (updateFilePath, _countof(updateFilePath)-1, TEXT("%s\\updates\\updater.exe"), lpAppDataPath);

                        //note, can't use CreateProcess to launch as admin.
                        SHELLEXECUTEINFO execInfo;

                        zero(&execInfo, sizeof(execInfo));

                        execInfo.cbSize = sizeof(execInfo);
                        execInfo.lpFile = updateFilePath;
#ifndef _WIN64
                        execInfo.lpParameters = TEXT("Win32");
#else
                        execInfo.lpParameters = TEXT("Win64");
#endif
                        execInfo.lpDirectory = cwd;
                        execInfo.nShow = SW_SHOWNORMAL;

                        if (!ShellExecuteEx (&execInfo))
                        {
                            AppWarning(TEXT("Can't launch updater '%s': %d"), updateFilePath, GetLastError());
                            goto abortUpdate;
                        }

                        //force OBS to perform another update check immediately after updating in case of issues
                        //with the new version
                        GlobalConfig->SetInt(TEXT("General"), TEXT("LastUpdateCheck"), 0);

                        //since we're in a separate thread we can't just PostQuitMessage ourselves
                        SendMessage(hwndMain, WM_CLOSE, 0, 0);
                    }
                }
            }
        }
    }

abortUpdate:

    CryptReleaseContext(hProvider, 0);

    return 0;
}
Exemple #14
0
void GraphicsCaptureSource::AttemptCapture()
{
    OSDebugOut(TEXT("attempting to capture..\n"));

    if (scmpi(strWindowClass, L"dwm") == 0)
    {
        hwndTarget = FindWindow(strWindowClass, NULL);
    }
    else
    {
        FindWindowData fwd;

        //FIXME: duplicated code, but we need OpenProcess here
        char pOPStr[12];
        mcpy(pOPStr, "NpflUvhel{x", 12); //OpenProcess obfuscated
        for (int i = 0; i<11; i++) pOPStr[i] ^= i ^ 1;

        fwd.pOpenProcess = (OPPROC)GetProcAddress(GetModuleHandle(TEXT("KERNEL32")), pOPStr);
        fwd.classname = strWindowClass;
        fwd.exename = strExecutable;
        fwd.hwnd = nullptr;

        EnumWindows(GraphicsCaptureFindWindow, (LPARAM)&fwd);

        hwndTarget = fwd.hwnd;
    }
    
    // use foregroundwindow as fallback (should be NULL if not using hotkey capture)
    if (!hwndTarget)
        hwndTarget = hwndNextTarget;

    hwndNextTarget = nullptr;
    
    OSDebugOut(L"Window: %s: ", strWindowClass.Array());
    if (hwndTarget)
    {
        OSDebugOut(L"Valid window\n");
        targetThreadID = GetWindowThreadProcessId(hwndTarget, &targetProcessID);
        if (!targetThreadID || !targetProcessID)
        {
            AppWarning(TEXT("GraphicsCaptureSource::AttemptCapture: GetWindowThreadProcessId failed, GetLastError = %u"), GetLastError());
            bErrorAcquiring = true;
            return;
        }
    }
    else
    {
        OSDebugOut(L"Bad window\n");
        if (!bUseHotkey && !warningID)
        {
            //Log(TEXT("GraphicsCaptureSource::AttemptCapture: Window '%s' [%s] not found."), strWindowClass.Array(), strExecutable.Array());
            //warningID = API->AddStreamInfo(Str("Sources.SoftwareCaptureSource.WindowNotFound"), StreamInfoPriority_High);
        }

        bCapturing = false;

        return;
    }

    if (injectHelperProcess && WaitForSingleObject(injectHelperProcess, 0) == WAIT_TIMEOUT)
        return;

    if(warningID)
    {
        //API->RemoveStreamInfo(warningID);
        warningID = 0;
    }

    //-------------------------------------------
    // see if we already hooked the process.  if not, inject DLL

    char pOPStr[12];
    mcpy(pOPStr, "NpflUvhel{x", 12); //OpenProcess obfuscated
    for (int i=0; i<11; i++) pOPStr[i] ^= i^1;

    OPPROC pOpenProcess = (OPPROC)GetProcAddress(GetModuleHandle(TEXT("KERNEL32")), pOPStr);

    DWORD permission = useSafeHook ? (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ) : (PROCESS_ALL_ACCESS);

    HANDLE hProcess = (*pOpenProcess)(permission, FALSE, targetProcessID);
    if(hProcess)
    {
        DWORD dwSize = MAX_PATH;
        wchar_t processName[MAX_PATH];
        memset(processName, 0, sizeof(processName));

        QueryFullProcessImageName(hProcess, 0, processName, &dwSize);

        if (dwSize != 0 && scmpi(processName, lastProcessName) != 0)
        {
            if (processName[0])
            {
                wchar_t *fileName = srchr(processName, '\\');
                Log(L"Trying to hook process: %s", (fileName ? fileName+1 : processName));
            }
            scpy_n(lastProcessName, processName, MAX_PATH-1);
        }

        //-------------------------------------------
        // load keepalive event

        hOBSIsAlive = CreateEvent(NULL, FALSE, FALSE, String() << OBS_KEEPALIVE_EVENT << UINT(targetProcessID));

        //-------------------------------------------

        hwndCapture = hwndTarget;

        hSignalRestart = OpenEvent(EVENT_ALL_ACCESS, FALSE, String() << RESTART_CAPTURE_EVENT << UINT(targetProcessID));
        if(hSignalRestart)
        {
            OSDebugOut(L"Setting signal for process ID %u\n", targetProcessID);

            SetEvent(hSignalRestart);
            bCapturing = true;
            captureWaitCount = 0;
        }
        else
        {
            BOOL bSameBit = TRUE;
            BOOL b32bit = TRUE;

            if (Is64BitWindows())
            {
                BOOL bCurrentProcessWow64, bTargetProcessWow64;
                IsWow64Process(GetCurrentProcess(), &bCurrentProcessWow64);
                IsWow64Process(hProcess, &bTargetProcessWow64);

                bSameBit = (bCurrentProcessWow64 == bTargetProcessWow64);
            }

            if(Is64BitWindows())
                IsWow64Process(hProcess, &b32bit);

            //verify the hook DLL is accessible
            String strDLL;
            DWORD dwDirSize = GetCurrentDirectory(0, NULL);
            strDLL.SetLength(dwDirSize);
            GetCurrentDirectory(dwDirSize, strDLL);

            strDLL << TEXT("\\plugins\\GraphicsCapture\\GraphicsCaptureHook");

            if (!b32bit)
                strDLL << TEXT("64");

            strDLL << TEXT(".dll");

            if (!CheckFileIntegrity(strDLL.Array()))
            {
                OSDebugOut(L"Error acquiring\n");
                bErrorAcquiring = true;
            }
            else
            {

                if (bSameBit && !useSafeHook)
                {
                    if (InjectLibrary(hProcess, strDLL))
                    {
                        captureWaitCount = 0;
                        OSDebugOut(L"Inject successful\n");
                        bCapturing = true;
                    }
                    else
                    {
                        AppWarning(TEXT("GraphicsCaptureSource::AttemptCapture: Failed to inject library, GetLastError = %u"), GetLastError());
                        bErrorAcquiring = true;
                    }
                }
                else
                {
                    String strDLLPath;
                    DWORD dwDirSize = GetCurrentDirectory(0, NULL);
                    strDLLPath.SetLength(dwDirSize);
                    GetCurrentDirectory(dwDirSize, strDLLPath);

                    strDLLPath << TEXT("\\plugins\\GraphicsCapture");

                    String strHelper = strDLLPath;
                    strHelper << ((b32bit) ? TEXT("\\injectHelper.exe") : TEXT("\\injectHelper64.exe"));

                    if (!CheckFileIntegrity(strHelper.Array()))
                    {
                        bErrorAcquiring = true;
                    }
                    else
                    {
                        String strCommandLine;
                        strCommandLine << TEXT("\"") << strHelper << TEXT("\" ");
                        if (useSafeHook)
                            strCommandLine << UIntString(targetThreadID) << " 1";
                        else
                            strCommandLine << UIntString(targetProcessID) << " 0";

                        //---------------------------------------

                        PROCESS_INFORMATION pi;
                        STARTUPINFO si;

                        zero(&pi, sizeof(pi));
                        zero(&si, sizeof(si));
                        si.cb = sizeof(si);

                        if (CreateProcess(strHelper, strCommandLine, NULL, NULL, FALSE, 0, NULL, strDLLPath, &si, &pi))
                        {
                            int exitCode = 0;

                            CloseHandle(pi.hThread);

                            if (!useSafeHook)
                            {
                                WaitForSingleObject(pi.hProcess, INFINITE);
                                GetExitCodeProcess(pi.hProcess, (DWORD*)&exitCode);
                                CloseHandle(pi.hProcess);
                            }
                            else
                            {
                                injectHelperProcess = pi.hProcess;
                            }

                            if (exitCode == 0)
                            {
                                captureWaitCount = 0;
                                bCapturing = true;
                            }
                            else
                            {
                                AppWarning(TEXT("GraphicsCaptureSource::AttemptCapture: Failed to inject library, error code = %d"), exitCode);
                                bErrorAcquiring = true;
                            }
                        }
                        else
                        {
                            AppWarning(TEXT("GraphicsCaptureSource::AttemptCapture: Could not create inject helper, GetLastError = %u"), GetLastError());
                            bErrorAcquiring = true;
                        }
                    }
                }
            }
        }

        //save a copy of the process handle which we injected into, this lets us check for process exit in Tick()
        if (!hTargetProcess)
        {
            if (!DuplicateHandle(GetCurrentProcess(), hProcess, GetCurrentProcess(), &hTargetProcess, 0, FALSE, DUPLICATE_SAME_ACCESS))
            {
                Log(TEXT("Warning: Couldn't DuplicateHandle, %d"), GetLastError());
            }
        }

        CloseHandle(hProcess);

        if (!bCapturing)
        {
            CloseHandle(hOBSIsAlive);
            hOBSIsAlive = NULL;
        }
    }
    else
    {
        AppWarning(TEXT("GraphicsCaptureSource::AttemptCapture: OpenProcess failed, GetLastError = %u"), GetLastError());
        bErrorAcquiring = true;
    }
}