static void* vpl_monitor_dir_handler(void* unused) { int rc; while(true) { rc = VPLSem_Wait(&g_semaphoreCommand); if(rc != VPL_OK) { VPL_REPORT_WARN("Semaphore wait:%d", rc); } g_returnErrorCode = 0; VPL_REPORT_INFO("Command Received:%d", g_monitorCommand); switch(g_monitorCommand) { case MONITOR_COMMAND_NONE: break; case MONITOR_COMMAND_START: rc = beginMonitor(g_monitorHandle); if(rc != 0) { VPL_REPORT_WARN("Cannot begin monitor:%d", rc); g_returnErrorCode = rc; }else { g_monitorHandles.push_back(g_monitorHandle); } g_monitorCommand = MONITOR_COMMAND_NONE; rc = VPLSem_Post(&g_semaphoreReturn); if(rc != VPL_OK){ VPL_REPORT_WARN("Semaphore Return post:%d", rc); g_returnErrorCode = rc; } break; case MONITOR_COMMAND_STOP: g_monitorHandle->stop = true; #ifdef VPL_PLAT_IS_WINRT // TODO: properly stop dir monitoring rc = VPL_ERR_NOOP; #else if (CancelIo(g_monitorHandle->hDir) == 0) { rc = VPLError_GetLastWinError(); VPL_REPORT_WARN("CancelIo:%d", rc); } #endif g_monitorHandles.erase(std::remove(g_monitorHandles.begin(), g_monitorHandles.end(), g_monitorHandle), g_monitorHandles.end()); g_monitorCommand = MONITOR_COMMAND_NONE; rc = VPLSem_Post(&g_semaphoreReturn); if(rc != VPL_OK){ VPL_REPORT_WARN("Semaphore Return post:%d", rc); g_returnErrorCode = rc; } break; case MONITOR_COMMAND_DESTROY: { std::vector<VPLFS_MonitorHandle_t*>::iterator iter = g_monitorHandles.begin(); for(;iter!=g_monitorHandles.end();++iter) { (*iter)->stop = true; #ifdef VPL_PLAT_IS_WINRT // TODO: properly stop dir monitoring rc = VPL_ERR_NOOP; #else if (CancelIo((*iter)->hDir) == 0) { rc = VPLError_GetLastWinError(); VPL_REPORT_WARN("CancelIo:%d", rc); } #endif } g_monitorHandles.clear(); } g_monitorCommand = MONITOR_COMMAND_NONE; goto exit; default: VPL_REPORT_WARN("Unrecognized command: %d", rc); break; } } exit: return NULL; }
ServerWindow::ServerWindow(QWidget* parent) :QWidget(parent) { setWindowTitle("Qt TasServer Ui"); monitor = new ServerMonitor(); statusButton = new QPushButton("Check status"); stopButton = new QPushButton("Stop"); startButton = new QPushButton("Start"); resetButton = new QPushButton ("Reset server"); loadPluginsButton = new QPushButton("Load Plugins"); #ifdef Q_OS_SYMBIAN pluginButton = new QPushButton ("Enable tas"); autoStart = new QCheckBox("Autostart"); autoStart->setTristate(false); if(monitor->autostartState()){ autoStart->setCheckState(Qt::Checked); } connect(autoStart, SIGNAL(toggled(bool)), monitor, SLOT(setAutoStart(bool))); #endif QLabel* stateLabel = new QLabel("Server state:"); QLabel* versionLabel = new QLabel("Server version:"); QLabel* stateValue = new QLabel("Unknown"); QLabel* versionValue = new QLabel(TAS_VERSION); QLabel* hostBindingLabel = new QLabel("Server Address Binding:"); anyBindRadioButton = new QRadioButton("Any"); localBindRadioButton = new QRadioButton("Localhost"); anyBindRadioButton->setDisabled(true); localBindRadioButton->setDisabled(true); connect(monitor, SIGNAL(serverState(const QString&)), stateValue, SLOT(setText(const QString&))); connect(monitor, SIGNAL(beginMonitor()), this, SLOT(disableButtons())); connect(monitor, SIGNAL(stopMonitor()), this, SLOT(enableButtons())); connect(monitor, SIGNAL(disableReBinding()), this, SLOT(disableRadioButtons())); connect(monitor, SIGNAL(enableReBinding(const QString&)), this, SLOT(enableRadioButtons(const QString&))); QTextEdit* editField = new QTextEdit(); editField->setReadOnly(true); connect(monitor, SIGNAL(serverDebug(const QString&)), editField, SLOT(append(const QString&))); connect(startButton, SIGNAL(clicked()), editField, SLOT(clear())); connect(stopButton, SIGNAL(clicked()), editField, SLOT(clear())); connect(resetButton, SIGNAL(clicked()), editField, SLOT(clear())); connect(statusButton, SIGNAL(clicked()), editField, SLOT(clear())); connect(loadPluginsButton, SIGNAL(clicked()), editField, SLOT(clear())); connect(anyBindRadioButton, SIGNAL(clicked()), editField, SLOT(clear())); connect(localBindRadioButton, SIGNAL(clicked()), editField, SLOT(clear())); connect(anyBindRadioButton, SIGNAL(clicked()), monitor, SLOT(setAnyBinding())); connect(localBindRadioButton, SIGNAL(clicked()), monitor, SLOT(setLocalBinding())); #ifdef Q_OS_SYMBIAN connect(pluginButton, SIGNAL(clicked()), editField, SLOT(clear())); connect(pluginButton, SIGNAL(clicked()), monitor, SLOT(enablePluginLoad())); #endif connect(statusButton, SIGNAL(clicked()), monitor, SLOT(serverState())); connect(stopButton, SIGNAL(clicked()), monitor, SLOT(stopServer())); connect(startButton, SIGNAL(clicked()), monitor, SLOT(startServer())); connect(resetButton, SIGNAL(clicked()), monitor, SLOT(restartServer())); connect(loadPluginsButton, SIGNAL(clicked()),monitor, SLOT(loadPlugins())); QPushButton* quitButton = new QPushButton("Quit"); connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit())); QGridLayout* mainLayout = new QGridLayout(); mainLayout->addWidget(stateLabel, 0, 0, 1, 1); mainLayout->addWidget(stateValue, 0, 1, 1, 1); mainLayout->addWidget(versionLabel, 1, 0); mainLayout->addWidget(versionValue, 1, 1); // Server binding Radio mainLayout->addWidget(hostBindingLabel, 2, 0); mainLayout->addWidget(anyBindRadioButton, 2, 1); mainLayout->addWidget(localBindRadioButton, 3, 1); mainLayout->addWidget(editField, 4,0, 1, 2); #ifdef Q_OS_SYMBIAN mainLayout->addWidget(statusButton, 5, 0); mainLayout->addWidget(pluginButton, 5, 1); #else mainLayout->addWidget(statusButton, 5, 0); mainLayout->addWidget(loadPluginsButton, 5, 1); #endif mainLayout->addWidget(stopButton, 6, 0); mainLayout->addWidget(startButton, 6, 1); mainLayout->addWidget(resetButton, 7, 0); mainLayout->addWidget(quitButton, 7, 1); #ifdef Q_OS_SYMBIAN mainLayout->addWidget(autoStart, 8, 0); mainLayout->addWidget(loadPluginsButton, 8, 1); #endif setLayout(mainLayout); // QRect rect = qApp->desktop()->screenGeometry(); // if(rect.width() > 864) // setFixedSize(350,600); // else{ // showFullScreen(); // } }
VOID CALLBACK ChDirCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { //VPL_REPORT_INFO("ChDirCompletionRoutine"); int rc; DWORD dwOffset = 0; FILE_NOTIFY_INFORMATION* pInfo; VPLFS_MonitorHandle_t* monHandle = (VPLFS_MonitorHandle_t*)(lpOverlapped->hEvent); if(dwErrorCode==ERROR_OPERATION_ABORTED || g_isInitCount==0 || monHandle->stop) { // Will be handled below. }else if(dwErrorCode != ERROR_SUCCESS) { VPL_REPORT_WARN("Unexpected error:"FMT_DWORD, dwErrorCode); }else { // (dwErrorCode == ERROR_SUCCESS), btw, ERROR_SUCCESS == 0. DWORD nextEntryOffset = 1; VPLFS_MonitorEvent* cbBuffer = (VPLFS_MonitorEvent*) (monHandle->pBuffer+monHandle->nBufferLength); u32 previousEntry = 0; void* eventBuffer = cbBuffer; int eventBufferSize = 0; if(dwNumberOfBytesTransfered == 0) { // This means the buffer overflowed monHandle->cb(monHandle, eventBuffer, eventBufferSize, VPLFS_MonitorCB_OVERFLOW); }else { do { // Get a pointer to the first change record... pInfo = (FILE_NOTIFY_INFORMATION*) &(monHandle->pBuffer[dwOffset]); nextEntryOffset = pInfo->NextEntryOffset; char filename[4 * MAX_PATH]; // a UTF16 char may require at most 4 bytes when encoded in UTF8 // NOTE: pInfo->FileName is not null-terminated! // NOTE: pInfo->FileNameLength is in bytes! int temp_rc = _VPL__wstring_to_utf8(pInfo->FileName, pInfo->FileNameLength / sizeof(WCHAR), filename, ARRAY_SIZE_IN_BYTES(filename)); if(temp_rc != 0) { VPL_REPORT_WARN("%s failed: %d", "_VPL__wstring_to_utf8", temp_rc); // TODO: skip the rest of this loop? } if(!isBeginWithPeriod(filename)) { // If the file is not considered hidden (begins with a period. //VPL_REPORT_INFO("Filename:%s, FilenameLength:"FMT_DWORD", action:"FMT_DWORD", nextEntry:"FMT_DWORD, // filename, pInfo->FileNameLength, pInfo->Action, pInfo->NextEntryOffset); switch(pInfo->Action) { case FILE_ACTION_ADDED: { //VPL_REPORT_INFO("FILE_ACTION_ADDED: %s", filename); cbBuffer->action = VPLFS_MonitorEvent_FILE_ADDED; monHandle->has_rename_old_name = false; setCommon(cbBuffer, filename); previousEntry = cbBuffer->nextEntryOffsetBytes; eventBufferSize += cbBuffer->nextEntryOffsetBytes; cbBuffer = (VPLFS_MonitorEvent*)(((char*)(cbBuffer))+cbBuffer->nextEntryOffsetBytes); }break; case FILE_ACTION_REMOVED: { //VPL_REPORT_INFO("FILE_ACTION_REMOVED: %s", filename); cbBuffer->action = VPLFS_MonitorEvent_FILE_REMOVED; monHandle->has_rename_old_name = false; setCommon(cbBuffer, filename); previousEntry = cbBuffer->nextEntryOffsetBytes; eventBufferSize += cbBuffer->nextEntryOffsetBytes; cbBuffer = (VPLFS_MonitorEvent*)(((char*)(cbBuffer))+cbBuffer->nextEntryOffsetBytes); }break; case FILE_ACTION_MODIFIED: { //VPL_REPORT_INFO("FILE_ACTION_MODIFIED: %s", filename); cbBuffer->action = VPLFS_MonitorEvent_FILE_MODIFIED; monHandle->has_rename_old_name = false; setCommon(cbBuffer, filename); previousEntry = cbBuffer->nextEntryOffsetBytes; eventBufferSize += cbBuffer->nextEntryOffsetBytes; cbBuffer = (VPLFS_MonitorEvent*)(((char*)(cbBuffer))+cbBuffer->nextEntryOffsetBytes); }break; case FILE_ACTION_RENAMED_OLD_NAME: { //VPL_REPORT_INFO("FILE_ACTION_RENAMED_OLD_NAME: %s", filename); monHandle->has_rename_old_name = true; strncpy(monHandle->rename_old_name, filename, MAX_PATH); }break; case FILE_ACTION_RENAMED_NEW_NAME: { //VPL_REPORT_INFO("FILE_ACTION_RENAMED_NEW_NAME: %s", filename); if(monHandle->has_rename_old_name) { cbBuffer->action = VPLFS_MonitorEvent_FILE_RENAMED; setCommon(cbBuffer, monHandle->rename_old_name); cbBuffer->moveTo = ((char*)cbBuffer) + cbBuffer->nextEntryOffsetBytes; std::string moveToName(filename); replaceBackslashWithForwardSlash(moveToName); strncpy((char*)cbBuffer->moveTo, moveToName.c_str(), MAX_PATH); int nameLen = moveToName.size()+1; // +1 for '\0' cbBuffer->filename = (char*)(cbBuffer+1); cbBuffer->nextEntryOffsetBytes += ALIGN(nameLen); previousEntry = cbBuffer->nextEntryOffsetBytes; eventBufferSize += cbBuffer->nextEntryOffsetBytes; cbBuffer = (VPLFS_MonitorEvent*)(((char*)(cbBuffer))+cbBuffer->nextEntryOffsetBytes); monHandle->has_rename_old_name = false; }else{ VPL_REPORT_WARN("RENAMED_NEW_NAME without RENAME_OLD_NAME:%s", filename); } }break; default: VPL_REPORT_WARN("Unhandled action:"FMT_DWORD", %s", pInfo->Action, filename); break; } } // More than one change may happen at the same time. Load the next change and continue... dwOffset += pInfo->NextEntryOffset; }while((pInfo->NextEntryOffset != 0) && (dwOffset<dwNumberOfBytesTransfered) && (monHandle->stop != true)); cbBuffer = (VPLFS_MonitorEvent*)(((char*)cbBuffer)- previousEntry); cbBuffer->nextEntryOffsetBytes = 0; if(eventBufferSize>0) { monHandle->cb(monHandle, eventBuffer, eventBufferSize, VPLFS_MonitorCB_OK); } } } if(g_isInitCount==0 || monHandle->stop) { VPL_REPORT_INFO("Cleaned up file monitor"); CloseHandle(monHandle->hDir); free(monHandle); } else { rc = beginMonitor(monHandle); if(rc != 0) { VPL_REPORT_WARN("beginMonitor failed:%d", rc); } } }