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); }
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); } }
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; }
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(); }
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(); }