ObCreateSymbolicLink/ObDeleteSymbolicLink

This commit is contained in:
Dr. Chat 2015-12-17 17:14:43 -06:00 committed by Ben Vanik
parent 9cf324f689
commit 8f92c60a0b
3 changed files with 64 additions and 6 deletions

View File

@ -169,6 +169,37 @@ SHIM_CALL ObDereferenceObject_shim(PPCContext* ppc_context,
SHIM_SET_RETURN_32(0);
}
dword_result_t ObCreateSymbolicLink(pointer_t<X_ANSI_STRING> path,
pointer_t<X_ANSI_STRING> target) {
auto path_str = path->to_string(kernel_memory()->virtual_membase());
auto target_str = target->to_string(kernel_memory()->virtual_membase());
path_str = filesystem::CanonicalizePath(path_str);
target_str = filesystem::CanonicalizePath(target_str);
auto pos = path_str.find("\\??\\");
if (pos != path_str.npos && pos == 0) {
path_str = path_str.substr(4); // Strip the full qualifier
}
if (!kernel_state()->file_system()->RegisterSymbolicLink(path_str,
target_str)) {
return X_STATUS_UNSUCCESSFUL;
}
return X_STATUS_SUCCESS;
}
DECLARE_XBOXKRNL_EXPORT(ObCreateSymbolicLink, ExportTag::kImplemented);
dword_result_t ObDeleteSymbolicLink(pointer_t<X_ANSI_STRING> path) {
auto path_str = path->to_string(kernel_memory()->virtual_membase());
if (!kernel_state()->file_system()->UnregisterSymbolicLink(path_str)) {
return X_STATUS_UNSUCCESSFUL;
}
return X_STATUS_SUCCESS;
}
DECLARE_XBOXKRNL_EXPORT(ObDeleteSymbolicLink, ExportTag::kImplemented);
dword_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr,
dword_t options) {
// NOTE: new_handle_ptr can be zero to just close a handle.

View File

@ -36,6 +36,8 @@ bool VirtualFileSystem::RegisterSymbolicLink(std::string path,
std::string target) {
auto global_lock = global_critical_region_.Acquire();
symlinks_.insert({path, target});
XELOGD("Registered symbolic link: %s => %s", path.c_str(), target.c_str());
return true;
}
@ -45,10 +47,22 @@ bool VirtualFileSystem::UnregisterSymbolicLink(std::string path) {
if (it == symlinks_.end()) {
return false;
}
XELOGD("Unregistered symbolic link: %s => %s", it->first.c_str(),
it->second.c_str());
symlinks_.erase(it);
return true;
}
bool VirtualFileSystem::IsSymbolicLink(const std::string& path) {
auto global_lock = global_critical_region_.Acquire();
auto it = symlinks_.find(path);
if (it == symlinks_.end()) {
return false;
}
return true;
}
Entry* VirtualFileSystem::ResolvePath(std::string path) {
auto global_lock = global_critical_region_.Acquire();
@ -58,17 +72,29 @@ Entry* VirtualFileSystem::ResolvePath(std::string path) {
// Resolve symlinks.
std::string device_path;
std::string relative_path;
for (const auto& it : symlinks_) {
if (xe::find_first_of_case(normalized_path, it.first) == 0) {
// Found symlink!
device_path = it.second;
relative_path = normalized_path.substr(it.first.size());
for (int i = 0; i < 2; i++) {
for (const auto& it : symlinks_) {
if (xe::find_first_of_case(normalized_path, it.first) == 0) {
// Found symlink!
device_path = it.second;
if (relative_path.empty()) {
relative_path = normalized_path.substr(it.first.size());
}
// Bit of a cheaty move here, but allows double symlinks to be resolved.
normalized_path = device_path;
break;
}
}
// Break as soon as we've completely resolved the symlinks to a device.
if (!IsSymbolicLink(device_path)) {
break;
}
}
// Not to fret, check to see if the path is fully qualified.
if (device_path.empty()) {
// Symlink wasn't passed in - Check if we've received a raw device name.
for (auto& device : devices_) {
if (xe::find_first_of_case(normalized_path, device->mount_path()) == 0) {
device_path = device->mount_path();

View File

@ -32,6 +32,7 @@ class VirtualFileSystem {
bool RegisterSymbolicLink(std::string path, std::string target);
bool UnregisterSymbolicLink(std::string path);
bool IsSymbolicLink(const std::string& path);
Entry* ResolvePath(std::string path);
Entry* ResolveBasePath(std::string path);