// Ask for the thread to stop and waith until it ends void FileWatcher::SynchronousAbort() { SetEvent(hEvtStopWatching); if (hWatchingThread) { WaitForSingleObject(hWatchingThread, INFINITE); CloseHandle(hWatchingThread); hWatchingThread = NULL; } CloseHandle(overl.hEvent); overl.hEvent = NULL; // cf. https://code.google.com/p/sumatrapdf/issues/detail?id=2039 // we must wait for all outstanding overlapped i/o on hDir has stopped. // otherwise CloseHandle(hDir) might end up modyfing it's associated // overl asynchronously, after we have already freed its memory, causing // memory corruption BOOL ok = CancelIo(hDir); if (!ok) LogLastError(); DWORD numBytesTransferred; // TODO: do I need this at all? ok = GetOverlappedResult(hDir, &overl, &numBytesTransferred, FALSE); if (!ok) { DWORD err = GetLastError(); if (ERROR_OPERATION_ABORTED != err) LogLastError(); } CloseHandle(hDir); hDir = NULL; }
/* Undo what DoAssociateExeWithPdfExtension() in AppTools.cpp did */ static void UnregisterFromBeingDefaultViewer(HKEY hkey) { ScopedMem<WCHAR> curr(ReadRegStr(hkey, REG_CLASSES_PDF, nullptr)); ScopedMem<WCHAR> prev(ReadRegStr(hkey, REG_CLASSES_APP, L"previous.pdf")); if (!curr || !str::Eq(curr, APP_NAME_STR)) { // not the default, do nothing } else if (prev) { WriteRegStr(hkey, REG_CLASSES_PDF, nullptr, prev); } else { #pragma warning(push) #pragma warning(disable : 6387) // silence /analyze: '_Param_(3)' could be '0': this does not adhere to the specification for the function 'SHDeleteValueW' SHDeleteValue(hkey, REG_CLASSES_PDF, nullptr); #pragma warning(pop) } // the following settings overrule HKEY_CLASSES_ROOT\.pdf ScopedMem<WCHAR> buf(ReadRegStr(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT, PROG_ID)); if (str::Eq(buf, APP_NAME_STR)) { LONG res = SHDeleteValue(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT, PROG_ID); if (res != ERROR_SUCCESS) LogLastError(res); } buf.Set(ReadRegStr(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT, APPLICATION)); if (str::EqI(buf, EXENAME)) { LONG res = SHDeleteValue(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT, APPLICATION); if (res != ERROR_SUCCESS) LogLastError(res); } buf.Set(ReadRegStr(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT L"\\UserChoice", PROG_ID)); if (str::Eq(buf, APP_NAME_STR)) DeleteRegKey(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT L"\\UserChoice", true); }
// Get the SID of the user running this program (not necessarily the logged on user) // Returns NULL on error or the PSID on success static PSID GetCurrentSID() { HANDLE token; PSID sid = NULL; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { DWORD size = 0; // Get size of the TOKEN_USER data GetTokenInformation(token, TokenUser, NULL, 0, &size); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { LogLastError(TEXT("GetTokenInformation")); } else { TOKEN_USER *user = (TOKEN_USER*)LocalAlloc(0, size); if (GetTokenInformation(token, TokenUser, user, size, &size)) { // We need to copy the SID because the TOKEN_USER needs to be freed size -= sizeof(DWORD); sid = (PSID)memcpy(LocalAlloc(0, size), user->User.Sid, size); } else { LogLastError(TEXT("GetTokenInformation")); } LocalFree(user); } CloseHandle(token); } else { LogLastError(TEXT("OpenProcessToken")); } return sid; }
int SDL_KillProcess(SDL_ProcessInfo* pinfo, SDL_ProcessExitStatus* ps) { int success, status; if(!pinfo) { SDLTest_LogError("pinfo argument cannot be NULL"); return 0; } if(!ps) { SDLTest_LogError("ps argument cannot be NULL"); return 0; } success = kill(pinfo->pid, SIGKILL); if(success == -1) { LogLastError("kill() failed"); return 0; } success = waitpid(pinfo->pid, &status, 0); if(success == -1) { LogLastError("waitpid() failed"); return 0; } ps->exit_success = WIFEXITED(status); ps->exit_status = WEXITSTATUS(status); return 1; }
/* Undo what DoAssociateExeWithPdfExtension() in AppTools.cpp did */ static void UnregisterFromBeingDefaultViewer(HKEY hkey) { ScopedMem<WCHAR> curr(ReadRegStr(hkey, REG_CLASSES_PDF, NULL)); ScopedMem<WCHAR> prev(ReadRegStr(hkey, REG_CLASSES_APP, L"previous.pdf")); if (!curr || !str::Eq(curr, TAPP)) { // not the default, do nothing } else if (prev) { WriteRegStr(hkey, REG_CLASSES_PDF, NULL, prev); } else { SHDeleteValue(hkey, REG_CLASSES_PDF, NULL); } // the following settings overrule HKEY_CLASSES_ROOT\.pdf ScopedMem<WCHAR> buf(ReadRegStr(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT, PROG_ID)); if (str::Eq(buf, TAPP)) { LONG res = SHDeleteValue(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT, PROG_ID); if (res != ERROR_SUCCESS) LogLastError(res); } buf.Set(ReadRegStr(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT, APPLICATION)); if (str::EqI(buf, EXENAME)) { LONG res = SHDeleteValue(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT, APPLICATION); if (res != ERROR_SUCCESS) LogLastError(res); } buf.Set(ReadRegStr(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT L"\\UserChoice", PROG_ID)); if (str::Eq(buf, TAPP)) DeleteRegKey(HKEY_CURRENT_USER, REG_EXPLORER_PDF_EXT L"\\UserChoice", true); }
HANDLE GetProcessByName(_In_ TCHAR const *name, _Out_ DWORD &pid) { pid = 0; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snapshot == INVALID_HANDLE_VALUE) { Log("ERROR | GetProcessByName | Couldn't create process snapshot!"); LogLastError(); return nullptr; } PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(snapshot, &entry)) { Log("ERROR | GetProcessByName | Couldn't enumerate first process!"); LogLastError(); } else { while (Process32Next(snapshot, &entry)) { if (_tcscmp(entry.szExeFile, name) == 0) { pid = entry.th32ProcessID; break; } } } CloseHandle(snapshot); if (pid != 0) { Log("INFO | GetProcessByName | Found process", name); HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); if (process == nullptr) { Log("ERROR | GetProcessByName | Couldn't open process", name); LogLastError(); return nullptr; } else { return process; } } else { return nullptr; } }
DWORD PointerPath32::GetThreadAddress(_In_ HANDLE process, DWORD pId, unsigned int threadId) { HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (snapshot == INVALID_HANDLE_VALUE) { Log("ERROR | PointerPath::GetThreadAddress | Couldn't create thread snapshot!"); LogLastError(); return 0; } DWORD address = 0; THREADENTRY32 entry; entry.dwSize = sizeof(THREADENTRY32); if (Thread32First(snapshot, &entry)) { unsigned int currentId = 0; do { if (entry.th32OwnerProcessID == pId) { if (currentId == threadId) { HANDLE thread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT, FALSE, entry.th32ThreadID); if (thread == nullptr) { Log("ERROR | PointerPath::GetThreadAddress | Couldn't open thread with ID ", entry.th32ThreadID); LogLastError(); } else { address = GetStackStart(process, pId, thread); CloseHandle(thread); } break; } currentId += 1; } } while (Thread32Next(snapshot, &entry)); } else { Log("ERROR | PointerPath::GetThreadAddress | Couldn't enumerate first thread!"); LogLastError(); } CloseHandle(snapshot); return address; }
HANDLE GetLogFile(String path, _In_ FILETIME * const lolStartTime) { FILETIME creationTime; HANDLE file = GetNewestLog(path + TEXT("\\Logs\\Game - R3d Logs"), &creationTime); if (file == INVALID_HANDLE_VALUE) { Log("ERROR | GetLogReader | Couldn't open log file!"); LogLastError(); } else if (file == nullptr) { Log("INFO | GetLogReader | Couldn't find any log file, trying again"); } else { if (CompareFileTime(&creationTime, lolStartTime) >= 0) { return file; } else { Log("INFO | GetLogReader | Found log file was to old, waiting for the current log to be created"); } } return nullptr; }
int HardwareSerial::peek(void) { if (!_storageUsed) { if (!ReadFile(_comHandle, &_storage, 64, &_storageCount, NULL)) { #ifdef _DEBUG Log("Error %d when reading file: ", GetLastError()); LogLastError(); #endif return -1; } _storageUsed = true; _storageIndex = 0; // if nothing was read, return 0 and dont do anything if (_storageCount == 0) { _storageUsed = false; return -1; } } return _storage[_storageIndex]; }
int SDL_GetProcessExitStatus(SDL_ProcessInfo* pinfo, SDL_ProcessExitStatus* ps) { int success, status; if(!pinfo) { SDLTest_LogError("pinfo argument cannot be NULL"); return 0; } if(!ps) { SDLTest_LogError("ps argument cannot be NULL"); return 0; } success = waitpid(pinfo->pid, &status, WNOHANG); if(success == -1) { LogLastError("waitpid() failed"); return 0; } else if(success == 0) { ps->exit_status = -1; ps->exit_success = 1; } else { ps->exit_success = WIFEXITED(status); ps->exit_status = WEXITSTATUS(status); } return 1; }
static BOOL RemoveEmptyDirectory(WCHAR *dir) { WIN32_FIND_DATA findData; BOOL success = TRUE; ScopedMem<WCHAR> dirPattern(path::Join(dir, L"*")); HANDLE h = FindFirstFile(dirPattern, &findData); if (h != INVALID_HANDLE_VALUE) { do { ScopedMem<WCHAR> path(path::Join(dir, findData.cFileName)); DWORD attrs = findData.dwFileAttributes; // filter out directories. Even though there shouldn't be any // subdirectories, it also filters out the standard "." and ".." if ((attrs & FILE_ATTRIBUTE_DIRECTORY) && !str::Eq(findData.cFileName, L".") && !str::Eq(findData.cFileName, L"..")) { success &= RemoveEmptyDirectory(path); } } while (FindNextFile(h, &findData) != 0); FindClose(h); } if (!RemoveDirectory(dir)) { DWORD lastError = GetLastError(); if (ERROR_DIR_NOT_EMPTY != lastError && ERROR_FILE_NOT_FOUND != lastError) { LogLastError(lastError); success = FALSE; } } return success; }
HWND GetWindowById(DWORD pId) { HWND hwndCurrent = GetWindow(GetDesktopWindow(), GW_CHILD); if (hwndCurrent == nullptr) { Log("ERROR | GetWindowById | Couldn't get desktop window handle!"); LogLastError(); return nullptr; } DWORD pIdCurrent = 0; do { GetWindowThreadProcessId(hwndCurrent, &pIdCurrent); // checking for GetWindowTextLength to not equal 0 is to ensure that we found // the actual game window, not the small icon that pops up just before the game starts if (pIdCurrent == pId && IsWindowVisible(hwndCurrent) && GetWindowTextLength(hwndCurrent) != 0) { Log("INFO | GetWindowById | Found window with pId", pId); return hwndCurrent; } } while (hwndCurrent = GetNextWindow(hwndCurrent, GW_HWNDNEXT)); return nullptr; }
HANDLE GetNewestLog(_In_ TCHAR const * directory, _Out_ LPFILETIME const creationTime) { creationTime->dwHighDateTime = 0; creationTime->dwLowDateTime = 0; TCHAR dirPath[MAX_PATH]; size_t pathLength; if (FAILED(StringCchLength(directory, MAX_PATH, &pathLength)) || pathLength + 3 > MAX_PATH) { return INVALID_HANDLE_VALUE; } StringCchCopy(dirPath, MAX_PATH, directory); StringCchCat(dirPath, MAX_PATH, TEXT("\\*")); TCHAR newestLog[MAX_PATH]; newestLog[0] = '\0'; WIN32_FIND_DATA ffd; size_t nameLength; HANDLE searchHandle = FindFirstFile(dirPath, &ffd); if (searchHandle == INVALID_HANDLE_VALUE) { Log("ERROR | GetNewestLog | Couldn't enumerate files in", dirPath); LogLastError(); return nullptr; } do { if (SUCCEEDED(StringCchLength(ffd.cFileName, MAX_PATH, &nameLength)) && _tcscmp(ffd.cFileName + nameLength - 4, TEXT(".txt")) == 0 && CompareFileTime(&ffd.ftCreationTime, creationTime) == 1) { StringCchCopy(newestLog, MAX_PATH, ffd.cFileName); *creationTime = ffd.ftCreationTime; } } while (FindNextFile(searchHandle, &ffd) != 0); FindClose(searchHandle); TCHAR path[MAX_PATH]; if (FAILED(StringCchLength(newestLog, MAX_PATH, &nameLength)) || pathLength + nameLength > MAX_PATH) { return INVALID_HANDLE_VALUE; } StringCchCopy(path, MAX_PATH, directory); StringCchCat(path, MAX_PATH, TEXT("\\")); StringCchCat(path, MAX_PATH, newestLog); Log("INFO | GetNewestLog | Found newest log file at", path); return CreateFile(path, GENERIC_READ, // we only need to read FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // let LoL do whatever it pleases (Mundo!) nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); }
static bool CreateInstallationDirectory() { bool ok = dir::CreateAll(gGlobalData.installDir); if (!ok) { LogLastError(); NotifyFailed(_TR("Couldn't create the installation directory")); } return ok; }
void HardwareSerial::flush(void) { if (FlushFileBuffers(_comHandle) == 0) { #ifdef _DEBUG Log("Error %d when calling Flush: ", GetLastError()); LogLastError(); #endif } }
static void CALLBACK StopMonitoringDirAPC(ULONG_PTR arg) { WatchedDir* wd = (WatchedDir*)arg; lf("StopMonitoringDirAPC() wd=0x%p", wd); // this will cause ReadDirectoryChangesNotification() to be called // with errCode = ERROR_OPERATION_ABORTED BOOL ok = CancelIo(wd->hDir); if (!ok) LogLastError(); SafeCloseHandle(&wd->hDir); }
void HardwareSerial::end(void) { if (_comHandle != INVALID_HANDLE_VALUE && CloseHandle(_comHandle) == 0) { _comHandle = INVALID_HANDLE_VALUE; #ifdef _DEBUG Log("Error %d when closing Com Handle: ", GetLastError()); LogLastError(); #endif } }
static bool RemoveShortcut(bool allUsers) { ScopedMem<WCHAR> p(GetShortcutPath(allUsers)); if (!p.Get()) return false; bool ok = DeleteFile(p); if (!ok && (ERROR_FILE_NOT_FOUND != GetLastError())) { LogLastError(); return false; } return true; }
int SDL_LaunchProcess(char* file, char* args, SDL_ProcessInfo* pinfo) { pid_t pid; char** argv; if(!file) { SDLTest_LogError("file argument cannot be NULL"); return 0; } if(!pinfo) { SDLTest_LogError("pinfo cannot be NULL"); return 0; } pid = fork(); if(pid == -1) { LogLastError("fork() failed"); return 0; } else if(pid == 0) { /* parse the arguments string */ argv = SDLVisualTest_ParseArgsToArgv(args); argv[0] = file; execv(file, argv); LogLastError("execv() failed"); return 0; } else { pinfo->pid = pid; return 1; } /* never executed */ return 0; }
// Enable the SeTakeOwnership privilege so that we can take over the key // Returns TRUE on success, FALSE otherwise static BOOL EnableTakeOwnershipPriv() { HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tkprivs; BOOL retval = FALSE; ZeroMemory(&tkprivs, sizeof(tkprivs)); if (!OpenProcessToken(GetCurrentProcess(), (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY), &hToken)) { return LogLastError(TEXT("OpenProcessToken")); } if (LookupPrivilegeValue(NULL, SE_TAKE_OWNERSHIP_NAME, &luid)){ tkprivs.PrivilegeCount = 1; tkprivs.Privileges[0].Luid = luid; tkprivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!(retval = AdjustTokenPrivileges(hToken, FALSE, &tkprivs, sizeof(tkprivs), NULL, NULL))) { LogLastError(TEXT("AdjustTokenPrivileges")); } } else { LogLastError(TEXT("LookupPrivilegeValue")); } CloseHandle(hToken); return retval; }
_Success_(return) bool PointerPath32::GetModuleInfo(DWORD pId, _In_ TCHAR * moduleName, _Out_ MODULEENTRY32 &moduleInfo) { bool found = false; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pId); if (snapshot == INVALID_HANDLE_VALUE) { Log("ERROR | PointerPath::GetModuleInfo | Couldn't create module snapshot!"); LogLastError(); } else { MODULEENTRY32 entry; entry.dwSize = sizeof(MODULEENTRY32); if (!Module32First(snapshot, &entry)) { Log("ERROR | PointerPath::GetModuleInfo | Couldn't enumerate first module!"); LogLastError(); } else { do { if (_tcsicmp(entry.szModule, moduleName) == 0) { Log("INFO | PointerPath::GetModuleInfo | Found module", moduleName); moduleInfo = entry; found = true; break; } } while (Module32Next(snapshot, &entry)); } CloseHandle(snapshot); } return found; }
void HardwareSerial::begin(unsigned long baud, uint8_t config) { DCB dcb = dcbArray[config]; if ( _comPortName == L"\\\\.\\COM1" ) { g_pins.verifyPinFunction(0, FUNC_SER, BoardPinsClass::LOCK_FUNCTION); g_pins.verifyPinFunction(1, FUNC_SER, BoardPinsClass::LOCK_FUNCTION); pinMode(0, DIRECTION_IN); pinMode(1, DIRECTION_OUT); } _comHandle = CreateFile(_comPortName.c_str(), GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL); if (_comHandle == INVALID_HANDLE_VALUE) { #ifdef _DEBUG Log("Error %d due to invalid handle value: ", GetLastError()); LogLastError(); #endif return; } dcb.BaudRate = baud; if (SetCommState(_comHandle, &dcb) == 0) { #ifdef _DEBUG Log("Error %d when setting Com state: ", GetLastError()); LogLastError(); #endif return; } setTimeout(_timeout); }
// Try harder getting temporary directory // Caller needs to free() the result. // Returns NULL if fails for any reason. static WCHAR *GetValidTempDir() { ScopedMem<WCHAR> d(path::GetTempPath()); if (!d) { NotifyFailed(_TR("Couldn't obtain temporary directory")); return NULL; } bool ok = dir::Create(d); if (!ok) { LogLastError(); NotifyFailed(_TR("Couldn't create temporary directory")); return NULL; } return d.StealData(); }
// Try harder getting temporary directory // Caller needs to free() the result. // Returns NULL if fails for any reason. static WCHAR *GetValidTempDir() { WCHAR d[MAX_PATH]; DWORD res = GetTempPath(dimof(d), d); if ((0 == res) || (res >= MAX_PATH)) { NotifyFailed(L"Couldn't obtain temporary directory"); return NULL; } BOOL success = CreateDirectory(d, NULL); if (!success && (ERROR_ALREADY_EXISTS != GetLastError())) { LogLastError(); NotifyFailed(L"Couldn't create temporary directory"); return NULL; } return str::Dup(d); }
void HardwareSerial::end(void) { if (_comHandle != INVALID_HANDLE_VALUE) { if (CloseHandle(_comHandle) == 0) { #ifdef _DEBUG Log("Error %d when closing Com Handle: ", GetLastError()); LogLastError(); #endif } _comHandle = INVALID_HANDLE_VALUE; g_pins.verifyPinFunction(1, FUNC_DIO, BoardPinsClass::UNLOCK_FUNCTION); g_pins.verifyPinFunction(0, FUNC_DIO, BoardPinsClass::UNLOCK_FUNCTION); } }
static bool WriteToPipe(const byte *s, size_t len) { DWORD written; if (!gPipe) return false; DWORD toWrite = (DWORD)len; BOOL ok = WriteFile(gPipe, s, toWrite, &written, NULL); if (!ok) { lf("memtrace.dll: WriteToPipe() failed"); LogLastError(); ClosePipe(); return false; } if (written != toWrite) { lf("memtrace.dll: only wrote %d out of %d", (int)written, (int)toWrite); ClosePipe(); return false; } return true; }
int HardwareSerial::read(void) { if (_storageUsed) { if (_storageIndex + 1 >= _storageCount) { _storageUsed = false; } return _storage[_storageIndex++]; } else { if (!ReadFile(_comHandle, &_storage, 64, &_storageCount, NULL)) { #ifdef _DEBUG Log("Error %d when reading file: ", GetLastError()); LogLastError(); #endif return -1; } _storageUsed = true; _storageIndex = 0; // If only one character was read, then reset it if (_storageIndex + 1 >= _storageCount) { _storageUsed = false; } // if nothing was read, return 0 and dont do anything if (_storageCount == 0) { return -1; } return _storage[_storageIndex++]; } }
void HardwareSerial::setTimeout(unsigned long timeout) { _timeout = timeout; // Sets WIN32 READ/WRITE timeouts COMMTIMEOUTS CommTimeouts; GetCommTimeouts(_comHandle, &CommTimeouts); CommTimeouts.ReadIntervalTimeout = 0; CommTimeouts.ReadTotalTimeoutConstant = _timeout; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.WriteTotalTimeoutConstant = _timeout; CommTimeouts.WriteTotalTimeoutMultiplier = 0; if (!SetCommTimeouts(_comHandle, &CommTimeouts)) { #ifdef _DEBUG Log("Error %d when setting Com timeouts: ", GetLastError()); LogLastError(); #endif } }
int SDL_IsProcessRunning(SDL_ProcessInfo* pinfo) { int success; if(!pinfo) { SDLTest_LogError("pinfo cannot be NULL"); return -1; } success = kill(pinfo->pid, 0); if(success == -1) { if(errno == ESRCH) /* process is not running */ return 0; else { LogLastError("kill() failed"); return -1; } } return 1; }
bool SerialPort::Open(const TCHAR *path, unsigned _baud_rate) { assert(!Thread::IsInside()); #ifdef _WIN32_WCE is_widcomm = IsWidcommDevice(path); #endif DCB PortDCB; // Open the serial port. hPort = CreateFile(path, GENERIC_READ | GENERIC_WRITE, // Access (read-write) mode 0, // Share mode NULL, // Pointer to the security attribute OPEN_EXISTING,// How to open the serial port #ifdef _WIN32_WCE FILE_ATTRIBUTE_NORMAL, // Port attributes #else FILE_FLAG_OVERLAPPED, // Overlapped I/O #endif NULL); // Handle to port with attribute to copy // If it fails to open the port, return false. if (hPort == INVALID_HANDLE_VALUE) { LogLastError(_T("Failed to open port '%s'"), path); return false; } baud_rate = _baud_rate; PortDCB.DCBlength = sizeof(DCB); // Get the default port setting information. GetCommState(hPort, &PortDCB); // Change the DCB structure settings. PortDCB.BaudRate = baud_rate; // Current baud PortDCB.fBinary = true; // Binary mode; no EOF check PortDCB.fParity = true; // Enable parity checking PortDCB.fOutxCtsFlow = false; // No CTS output flow control PortDCB.fOutxDsrFlow = false; // No DSR output flow control PortDCB.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type PortDCB.fDsrSensitivity = false; // DSR sensitivity PortDCB.fTXContinueOnXoff = true; // XOFF continues Tx PortDCB.fOutX = false; // No XON/XOFF out flow control PortDCB.fInX = false; // No XON/XOFF in flow control PortDCB.fErrorChar = false; // Disable error replacement PortDCB.fNull = false; // Disable null removal PortDCB.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control PortDCB.fAbortOnError = true; // JMW abort reads/writes on error PortDCB.ByteSize = 8; // Number of bits/byte, 4-8 PortDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space PortDCB.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2 PortDCB.EvtChar = '\n'; // wait for end of line // Configure the port according to the specifications of the DCB structure. if (!SetCommState(hPort, &PortDCB)) { LogLastError(_T("Failed to configure port '%s'"), path); CloseHandle(hPort); hPort = INVALID_HANDLE_VALUE; return false; } SetupComm(hPort, 1024, 1024); // Direct the port to perform extended functions SETDTR and SETRTS // SETDTR: Sends the DTR (data-terminal-ready) signal. EscapeCommFunction(hPort, SETDTR); // SETRTS: Sends the RTS (request-to-send) signal. EscapeCommFunction(hPort, SETRTS); StoppableThread::Start(); return true; }