Ejemplo n.º 1
0
        String Win32Window::GetTitle()
        {
            int l = GetWindowTextLengthW(hWnd);
            if (l == 0) return String();

            Utf16String titleW = Utf16String::Create(l);
            l = GetWindowText(hWnd, titleW.Ptr(), l);

            return Unicode::Utf16To8(titleW);
        }
Ejemplo n.º 2
0
        Win32Window::Win32Window(int width, int height, const Xli::String& title, int flags)
        {
            this->ownsHwnd = true;
            this->closed = false;
            this->fullscreen = false;
            this->eventHandler = eventHandler;

            if (flags & WindowFlagsFullscreen)
            {
                flags &= ~WindowFlagsFullscreen;
                fullscreen = true;
            }

            rect.top = 0;
            rect.left = 0;
            rect.bottom = height;
            rect.right = width;

            dwStyle = StyleFromXliWindowFlags(flags);
            AdjustWindowRect(&rect, dwStyle, 0);

            Utf16String titleW = Unicode::Utf8To16(title);
            hWnd = CreateWindowW(WindowClassName, titleW.Ptr(), dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, 0, 0, HInstance, 0);

            if (!hWnd)
                XLI_THROW("Failed to create window: " + Win32::GetLastErrorString());

            if (!MainWindow)
                MainWindow = this;

            SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));

            ShowWindow(hWnd, SW_NORMAL);
            SetForegroundWindow(hWnd);
            SetFocus(hWnd);

            if (fullscreen)
            {
                fullscreen = false;
                SetFullscreen(true);
            }
        }
Ejemplo n.º 3
0
    File::File(const String& filename, FileMode mode)
    {
        const char* m = "rb";
        
        switch (mode)
        {
            case FileModeRead: m = "rb"; break;
            case FileModeWrite: m = "wb"; break;
            case FileModeAppend: m = "ab"; break;
            case FileModeReadWrite: m = "r+b"; break;
            case FileModeReadWriteNew: m = "w+b"; break;
            case FileModeReadAppend: m = "a+b"; break;
            default: XLI_THROW("Invalid file mode: " + FileModeInfo::ToString(mode));
        }
        
#ifdef XLI_COMPILER_MSVC
        
        fp = 0;
        
        Utf16String filenameW = Unicode::Utf8To16(filename);
        Utf16String mW = Unicode::Utf8To16(m);
        
        if (_wfopen_s(&fp, filenameW.Ptr(), mW.Ptr()) != 0)
            XLI_THROW_CANT_OPEN_FILE(filename);

#else
        
        fp = fopen(filename.Ptr(), m);
        if (!fp) XLI_THROW_CANT_OPEN_FILE(filename);

#endif

        this->flags = FileFlagsCanClose | FileFlagsCanSeek;
        
        if (mode & FileModeRead)
            this->flags |= FileFlagsCanRead;

        if ((mode & FileModeWrite) || (mode & FileModeAppend))
            this->flags |= FileFlagsCanWrite;
    }
Ejemplo n.º 4
0
 void Win32Window::SetTitle(const String& title)
 {
     Utf16String titleW = Unicode::Utf8To16(title);
     SetWindowTextW(hWnd, titleW.Ptr());
 }
 inline ReturnType operator()( Utf16String const & arg ) const
 {
     return arg.value();
 }
Ejemplo n.º 6
0
    jjm::Process* jjm::ProcessBuilder::spawn() const
    {   
        if (m_cmd.size() == 0)
            throw runtime_error("ProcessBuilder : Spawn failed. cmd empty.");
        if (m_cmd[0].size() == 0)
            throw runtime_error("ProcessBuilder : Spawn failed. cmd[0] empty.");

        Win32CreateProcessEnvWrapper envWrapper(m_hasCustomEnv, m_env);

        //cmd[0] is the name / path to the executable. 
        //If it contains a file separator character, then it should be 
        //interpreted as a path, which is precisely what giving to 
        //CreateProcessW as the lpApplicationName arg will do. 
        Utf16String applicationNameArg; 
        Utf8String newCmd0; 
        Path cmd0Path(m_cmd[0]); 
        if ( ! cmd0Path.getParent().isEmpty())
        {   applicationNameArg = makeU16Str(cmd0Path.getStringRep()); 
            newCmd0 = makeU8Str(applicationNameArg); 
        }
        wchar_t const * const applicationNameArgPointer = 
                applicationNameArg.size() ? applicationNameArg.c_str() : 0; 

        //Need to properly quote the command line for CreateProcess to parse
        //it because it's retarded and doesn't have argv, just a single
        //command arg string.
        jjm::UniqueArray<wchar_t*>  processArguments;
        createProcessArgumentsString(processArguments, m_argumentQuoting, m_cmd, newCmd0);

        FileHandleOwner pipeInReadEnd, pipeInWriteEnd;
        FileHandleOwner pipeOutReadEnd, pipeOutWriteEnd;
        FileHandleOwner pipeErrReadEnd, pipeErrWriteEnd;
        createPipes(*this, pipeInReadEnd, pipeInWriteEnd, pipeOutReadEnd, pipeOutWriteEnd, pipeErrReadEnd, pipeErrWriteEnd);

        vector<FileHandle> inheritableHandles;
        inheritableHandles.push_back(pipeInReadEnd.get());
        inheritableHandles.push_back(pipeOutWriteEnd.get());
        inheritableHandles.push_back(pipeErrWriteEnd.get());


        STARTUPINFOEXW startUpInfoEx;
        ZeroMemory(&startUpInfoEx, sizeof(STARTUPINFOEXW));
        startUpInfoEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);
        STARTUPINFOW* startUpInfoPtr = & startUpInfoEx.StartupInfo;
        DWORD const creationFlags = CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT;
        UniqueArray<HANDLE*> handlesList(0);
        UniqueArray<unsigned char*> memoryBackingAttributeList(0);
        struct FreeAttribList
        {   FreeAttribList() : x(0) {}
            PPROC_THREAD_ATTRIBUTE_LIST x;
            ~FreeAttribList() { if (x) DeleteProcThreadAttributeList(x); }
        } attribList;
        createAttributeList(handlesList, memoryBackingAttributeList, attribList.x, inheritableHandles);
        startUpInfoEx.lpAttributeList = attribList.x;

        startUpInfoPtr->dwFlags = STARTF_USESTDHANDLES;
        startUpInfoPtr->hStdInput  = pipeInReadEnd.get().native();
        startUpInfoPtr->hStdOutput = pipeOutWriteEnd.get().native();
        startUpInfoPtr->hStdError  = pipeErrWriteEnd.get().native();


        PROCESS_INFORMATION processInformation;
        ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION));

        Utf16String const u16dir = makeU16Str(m_dir.getStringRep());

        /* Make the handles that will become the child's stdin, stdout, and 
        stderr inheritable. When we do this, it's possible another thread can 
        call CreateProcess and inadvertently inherit these handles if they're
        not using the startUpInfoEx.lpAttributeList option to control which
        handles are inherited. We want to make this window of time where this
        is possible as short as possible. */
        for (size_t i=0; i<inheritableHandles.size(); ++i)
        {   if ( ! SetHandleInformation(inheritableHandles[i].native(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
                JFATAL(0, 0);
        }

        //allocate the process, and assign it an owner
        SetLastError(0); 
        BOOL const createProcessResult = ::CreateProcessW(
                    applicationNameArgPointer, 
                    processArguments.get(),
                    0, //security attributes, use default
                    0, //thread attributes, use default
                    TRUE,
                    creationFlags,
                    m_hasCustomEnv ? envWrapper.envarray.get() : 0, //0 is default env
                    u16dir.c_str(), //working dir for new process
                    startUpInfoPtr,
                    & processInformation
                    );
        DWORD const lastError = GetLastError();

        /* Close the inheritable handles that are child's stdin, stdout, and 
        stderr. The handles are inheritable, and it's possible another thread
        can call CreateProcess and inadvertently inherit these handles if
        they're not using the startUpInfoEx.lpAttributeList option to control 
        which handles are inherited. We want to make this window of time where 
        this is possible as short as possible. */
        pipeInReadEnd.reset(); 
        pipeOutWriteEnd.reset();
        pipeErrWriteEnd.reset();

        if ( ! createProcessResult)
        {   stringstream ss;
            ss << "ProcessBuilder : CreateProcessW(\n";
            if (applicationNameArgPointer == 0)
                ss << "NULL";
            else
                ss << "\"" << makeU8Str(applicationNameArg) << "\",\n";
            ss << "\"" << makeU8Str(Utf16String(processArguments.get())) << "\",\n"; 
            ss << "...) failed. Cause:\n";

            if (lastError == ERROR_FILE_NOT_FOUND)
                ss << "GetLastError() ERROR_FILE_NOT_FOUND, The system cannot find the file specified.";
            else if (lastError == ERROR_DIRECTORY)
                ss << "GetLastError() ERROR_DIRECTORY, directory is not valid [" << m_dir.getStringRep() << "].";
            else if (lastError == ERROR_ACCESS_DENIED)
                ss << "GetLastError() ERROR_ACCESS_DENIED, access is denied.";
            else if (lastError == ERROR_INVALID_PARAMETER)
                ss << "GetLastError() ERROR_INVALID_PARAMETER, The parameter is incorrect.";
            else
                ss << "GetLastError() " << lastError << "."; 
            throw std::runtime_error(ss.str());
        }

        //Gotta close this handle on a successful CreateProcess call, 
        //or we have a leak; quirk of the CreateProcess API.
        if ( ! CloseHandle(processInformation.hThread)) 
            JFATAL(0, 0);

        auto_ptr<Process> process(new Process);
        process->processHandle = processInformation.hProcess;
        process->processId = processInformation.dwProcessId;
        if (m_pipeIn)
            process->writeEndToChildsStdin.reset(pipeInWriteEnd.release());
        if (m_pipeOut)
            process->readEndFromChildsStdout.reset(pipeOutReadEnd.release());
        if (m_pipeErr)
            process->readEndFromChildsStderr.reset(pipeErrReadEnd.release());
        return process.release();
    }