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:
commit
9d924950cc
|
@ -111,6 +111,9 @@ dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr,
|
||||||
buttons.push_back(button);
|
buttons.push_back(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Broadcast XN_SYS_UI = true
|
||||||
|
kernel_state()->BroadcastNotification(0x9, true);
|
||||||
|
|
||||||
uint32_t chosen_button;
|
uint32_t chosen_button;
|
||||||
if (cvars::headless) {
|
if (cvars::headless) {
|
||||||
// Auto-pick the focused button.
|
// 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;
|
*result_ptr = chosen_button;
|
||||||
|
|
||||||
|
// Broadcast XN_SYS_UI = false
|
||||||
|
kernel_state()->BroadcastNotification(0x9, false);
|
||||||
|
|
||||||
if (overlapped) {
|
if (overlapped) {
|
||||||
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
||||||
return X_ERROR_IO_PENDING;
|
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;
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Broadcast XN_SYS_UI = true
|
||||||
|
kernel_state()->BroadcastNotification(0x9, true);
|
||||||
|
|
||||||
if (cvars::headless) {
|
if (cvars::headless) {
|
||||||
// Redirect default_text back into the buffer.
|
// Redirect default_text back into the buffer.
|
||||||
std::memset(buffer, 0, buffer_length * 2);
|
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());
|
xe::store_and_swap<std::wstring>(buffer, default_text.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Broadcast XN_SYS_UI = false
|
||||||
|
kernel_state()->BroadcastNotification(0x9, false);
|
||||||
|
|
||||||
if (overlapped) {
|
if (overlapped) {
|
||||||
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
||||||
return X_ERROR_IO_PENDING;
|
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);
|
out_text = out_text.substr(0, buffer_length - 1);
|
||||||
xe::store_and_swap<std::wstring>(buffer, out_text);
|
xe::store_and_swap<std::wstring>(buffer, out_text);
|
||||||
|
|
||||||
|
// Broadcast XN_SYS_UI = false
|
||||||
|
kernel_state()->BroadcastNotification(0x9, false);
|
||||||
|
|
||||||
if (overlapped) {
|
if (overlapped) {
|
||||||
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
||||||
return X_ERROR_IO_PENDING;
|
return X_ERROR_IO_PENDING;
|
||||||
|
@ -300,6 +315,10 @@ dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Broadcast XN_SYS_UI = true followed by XN_SYS_UI = false
|
||||||
|
kernel_state()->BroadcastNotification(0x9, true);
|
||||||
|
kernel_state()->BroadcastNotification(0x9, false);
|
||||||
|
|
||||||
if (overlapped) {
|
if (overlapped) {
|
||||||
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
|
||||||
return X_ERROR_IO_PENDING;
|
return X_ERROR_IO_PENDING;
|
||||||
|
|
|
@ -36,14 +36,7 @@ void XNotifyListener::EnqueueNotification(XNotificationID id, uint32_t data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
if (notifications_.count(id)) {
|
notifications_.push_back(std::pair<XNotificationID, uint32_t>(id, data));
|
||||||
// Already exists. Overwrite.
|
|
||||||
notifications_[id] = data;
|
|
||||||
} else {
|
|
||||||
// New.
|
|
||||||
notification_count_++;
|
|
||||||
notifications_.insert({id, data});
|
|
||||||
}
|
|
||||||
wait_handle_->Set();
|
wait_handle_->Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,14 +44,13 @@ bool XNotifyListener::DequeueNotification(XNotificationID* out_id,
|
||||||
uint32_t* out_data) {
|
uint32_t* out_data) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
bool dequeued = false;
|
bool dequeued = false;
|
||||||
if (notification_count_) {
|
if (notifications_.size()) {
|
||||||
dequeued = true;
|
dequeued = true;
|
||||||
auto it = notifications_.begin();
|
auto it = notifications_.begin();
|
||||||
*out_id = it->first;
|
*out_id = it->first;
|
||||||
*out_data = it->second;
|
*out_data = it->second;
|
||||||
notifications_.erase(it);
|
notifications_.erase(it);
|
||||||
notification_count_--;
|
if (!notifications_.size()) {
|
||||||
if (!notification_count_) {
|
|
||||||
wait_handle_->Reset();
|
wait_handle_->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,17 +61,22 @@ bool XNotifyListener::DequeueNotification(XNotificationID id,
|
||||||
uint32_t* out_data) {
|
uint32_t* out_data) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
bool dequeued = false;
|
bool dequeued = false;
|
||||||
if (notification_count_) {
|
if (!notifications_.size()) {
|
||||||
auto it = notifications_.find(id);
|
return dequeued;
|
||||||
if (it != notifications_.end()) {
|
}
|
||||||
|
|
||||||
|
for (auto it = notifications_.begin(); it != notifications_.end(); ++it) {
|
||||||
|
if (it->first != id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
dequeued = true;
|
dequeued = true;
|
||||||
*out_data = it->second;
|
*out_data = it->second;
|
||||||
notifications_.erase(it);
|
notifications_.erase(it);
|
||||||
notification_count_--;
|
if (!notifications_.size()) {
|
||||||
if (!notification_count_) {
|
|
||||||
wait_handle_->Reset();
|
wait_handle_->Reset();
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
return dequeued;
|
return dequeued;
|
||||||
}
|
}
|
||||||
|
@ -88,8 +85,8 @@ bool XNotifyListener::Save(ByteStream* stream) {
|
||||||
SaveObject(stream);
|
SaveObject(stream);
|
||||||
|
|
||||||
stream->Write(mask_);
|
stream->Write(mask_);
|
||||||
stream->Write(notification_count_);
|
stream->Write(notifications_.size());
|
||||||
if (notification_count_) {
|
if (notifications_.size()) {
|
||||||
for (auto pair : notifications_) {
|
for (auto pair : notifications_) {
|
||||||
stream->Write<uint32_t>(pair.first);
|
stream->Write<uint32_t>(pair.first);
|
||||||
stream->Write<uint32_t>(pair.second);
|
stream->Write<uint32_t>(pair.second);
|
||||||
|
@ -107,12 +104,12 @@ object_ref<XNotifyListener> XNotifyListener::Restore(KernelState* kernel_state,
|
||||||
notify->RestoreObject(stream);
|
notify->RestoreObject(stream);
|
||||||
notify->Initialize(stream->Read<uint64_t>());
|
notify->Initialize(stream->Read<uint64_t>());
|
||||||
|
|
||||||
notify->notification_count_ = stream->Read<size_t>();
|
auto notification_count_ = stream->Read<size_t>();
|
||||||
for (size_t i = 0; i < notify->notification_count_; i++) {
|
for (size_t i = 0; i < notification_count_; i++) {
|
||||||
std::pair<XNotificationID, uint32_t> pair;
|
std::pair<XNotificationID, uint32_t> pair;
|
||||||
pair.first = stream->Read<uint32_t>();
|
pair.first = stream->Read<uint32_t>();
|
||||||
pair.second = stream->Read<uint32_t>();
|
pair.second = stream->Read<uint32_t>();
|
||||||
notify->notifications_.insert(pair);
|
notify->notifications_.push_back(pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
return object_ref<XNotifyListener>(notify);
|
return object_ref<XNotifyListener>(notify);
|
||||||
|
|
|
@ -48,8 +48,7 @@ class XNotifyListener : public XObject {
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<xe::threading::Event> wait_handle_;
|
std::unique_ptr<xe::threading::Event> wait_handle_;
|
||||||
xe::global_critical_region global_critical_region_;
|
xe::global_critical_region global_critical_region_;
|
||||||
std::unordered_map<XNotificationID, uint32_t> notifications_;
|
std::vector<std::pair<XNotificationID, uint32_t>> notifications_;
|
||||||
size_t notification_count_ = 0;
|
|
||||||
uint64_t mask_ = 0;
|
uint64_t mask_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue