Merge pull request #1417 from emoose/xnotify-fixes

[Kernel] Make XamShow*UI exports send XN_SYS_UI notifications, & small XNotifyListener fix.
This commit is contained in:
Rick Gibbed 2019-08-03 22:37:59 -05:00 committed by GitHub
commit 9d924950cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 28 deletions

View File

@ -111,6 +111,9 @@ dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr,
buttons.push_back(button);
}
// Broadcast XN_SYS_UI = true
kernel_state()->BroadcastNotification(0x9, true);
uint32_t chosen_button;
if (cvars::headless) {
// Auto-pick the focused button.
@ -144,6 +147,9 @@ dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr,
}
*result_ptr = chosen_button;
// Broadcast XN_SYS_UI = false
kernel_state()->BroadcastNotification(0x9, false);
if (overlapped) {
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
return X_ERROR_IO_PENDING;
@ -232,6 +238,9 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
return X_ERROR_INVALID_PARAMETER;
}
// Broadcast XN_SYS_UI = true
kernel_state()->BroadcastNotification(0x9, true);
if (cvars::headless) {
// Redirect default_text back into the buffer.
std::memset(buffer, 0, buffer_length * 2);
@ -239,6 +248,9 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
xe::store_and_swap<std::wstring>(buffer, default_text.value());
}
// Broadcast XN_SYS_UI = false
kernel_state()->BroadcastNotification(0x9, false);
if (overlapped) {
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
return X_ERROR_IO_PENDING;
@ -269,6 +281,9 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
out_text = out_text.substr(0, buffer_length - 1);
xe::store_and_swap<std::wstring>(buffer, out_text);
// Broadcast XN_SYS_UI = false
kernel_state()->BroadcastNotification(0x9, false);
if (overlapped) {
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
return X_ERROR_IO_PENDING;
@ -300,6 +315,10 @@ dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type,
break;
}
// Broadcast XN_SYS_UI = true followed by XN_SYS_UI = false
kernel_state()->BroadcastNotification(0x9, true);
kernel_state()->BroadcastNotification(0x9, false);
if (overlapped) {
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
return X_ERROR_IO_PENDING;

View File

@ -36,14 +36,7 @@ void XNotifyListener::EnqueueNotification(XNotificationID id, uint32_t data) {
}
auto global_lock = global_critical_region_.Acquire();
if (notifications_.count(id)) {
// Already exists. Overwrite.
notifications_[id] = data;
} else {
// New.
notification_count_++;
notifications_.insert({id, data});
}
notifications_.push_back(std::pair<XNotificationID, uint32_t>(id, data));
wait_handle_->Set();
}
@ -51,14 +44,13 @@ bool XNotifyListener::DequeueNotification(XNotificationID* out_id,
uint32_t* out_data) {
auto global_lock = global_critical_region_.Acquire();
bool dequeued = false;
if (notification_count_) {
if (notifications_.size()) {
dequeued = true;
auto it = notifications_.begin();
*out_id = it->first;
*out_data = it->second;
notifications_.erase(it);
notification_count_--;
if (!notification_count_) {
if (!notifications_.size()) {
wait_handle_->Reset();
}
}
@ -69,17 +61,22 @@ bool XNotifyListener::DequeueNotification(XNotificationID id,
uint32_t* out_data) {
auto global_lock = global_critical_region_.Acquire();
bool dequeued = false;
if (notification_count_) {
auto it = notifications_.find(id);
if (it != notifications_.end()) {
if (!notifications_.size()) {
return dequeued;
}
for (auto it = notifications_.begin(); it != notifications_.end(); ++it) {
if (it->first != id) {
continue;
}
dequeued = true;
*out_data = it->second;
notifications_.erase(it);
notification_count_--;
if (!notification_count_) {
if (!notifications_.size()) {
wait_handle_->Reset();
}
}
break;
}
return dequeued;
}
@ -88,8 +85,8 @@ bool XNotifyListener::Save(ByteStream* stream) {
SaveObject(stream);
stream->Write(mask_);
stream->Write(notification_count_);
if (notification_count_) {
stream->Write(notifications_.size());
if (notifications_.size()) {
for (auto pair : notifications_) {
stream->Write<uint32_t>(pair.first);
stream->Write<uint32_t>(pair.second);
@ -107,12 +104,12 @@ object_ref<XNotifyListener> XNotifyListener::Restore(KernelState* kernel_state,
notify->RestoreObject(stream);
notify->Initialize(stream->Read<uint64_t>());
notify->notification_count_ = stream->Read<size_t>();
for (size_t i = 0; i < notify->notification_count_; i++) {
auto notification_count_ = stream->Read<size_t>();
for (size_t i = 0; i < notification_count_; i++) {
std::pair<XNotificationID, uint32_t> pair;
pair.first = stream->Read<uint32_t>();
pair.second = stream->Read<uint32_t>();
notify->notifications_.insert(pair);
notify->notifications_.push_back(pair);
}
return object_ref<XNotifyListener>(notify);

View File

@ -48,8 +48,7 @@ class XNotifyListener : public XObject {
private:
std::unique_ptr<xe::threading::Event> wait_handle_;
xe::global_critical_region global_critical_region_;
std::unordered_map<XNotificationID, uint32_t> notifications_;
size_t notification_count_ = 0;
std::vector<std::pair<XNotificationID, uint32_t>> notifications_;
uint64_t mask_ = 0;
};