ObCreateSymbolicLink/ObDeleteSymbolicLink
This commit is contained in:
parent
9cf324f689
commit
8f92c60a0b
|
@ -169,6 +169,37 @@ SHIM_CALL ObDereferenceObject_shim(PPCContext* ppc_context,
|
||||||
SHIM_SET_RETURN_32(0);
|
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_result_t NtDuplicateObject(dword_t handle, lpdword_t new_handle_ptr,
|
||||||
dword_t options) {
|
dword_t options) {
|
||||||
// NOTE: new_handle_ptr can be zero to just close a handle.
|
// NOTE: new_handle_ptr can be zero to just close a handle.
|
||||||
|
|
|
@ -36,6 +36,8 @@ bool VirtualFileSystem::RegisterSymbolicLink(std::string path,
|
||||||
std::string target) {
|
std::string target) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
symlinks_.insert({path, target});
|
symlinks_.insert({path, target});
|
||||||
|
XELOGD("Registered symbolic link: %s => %s", path.c_str(), target.c_str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,10 +47,22 @@ bool VirtualFileSystem::UnregisterSymbolicLink(std::string path) {
|
||||||
if (it == symlinks_.end()) {
|
if (it == symlinks_.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
XELOGD("Unregistered symbolic link: %s => %s", it->first.c_str(),
|
||||||
|
it->second.c_str());
|
||||||
|
|
||||||
symlinks_.erase(it);
|
symlinks_.erase(it);
|
||||||
return true;
|
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) {
|
Entry* VirtualFileSystem::ResolvePath(std::string path) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
||||||
|
@ -58,17 +72,29 @@ Entry* VirtualFileSystem::ResolvePath(std::string path) {
|
||||||
// Resolve symlinks.
|
// Resolve symlinks.
|
||||||
std::string device_path;
|
std::string device_path;
|
||||||
std::string relative_path;
|
std::string relative_path;
|
||||||
for (const auto& it : symlinks_) {
|
for (int i = 0; i < 2; i++) {
|
||||||
if (xe::find_first_of_case(normalized_path, it.first) == 0) {
|
for (const auto& it : symlinks_) {
|
||||||
// Found symlink!
|
if (xe::find_first_of_case(normalized_path, it.first) == 0) {
|
||||||
device_path = it.second;
|
// Found symlink!
|
||||||
relative_path = normalized_path.substr(it.first.size());
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not to fret, check to see if the path is fully qualified.
|
|
||||||
if (device_path.empty()) {
|
if (device_path.empty()) {
|
||||||
|
// Symlink wasn't passed in - Check if we've received a raw device name.
|
||||||
for (auto& device : devices_) {
|
for (auto& device : devices_) {
|
||||||
if (xe::find_first_of_case(normalized_path, device->mount_path()) == 0) {
|
if (xe::find_first_of_case(normalized_path, device->mount_path()) == 0) {
|
||||||
device_path = device->mount_path();
|
device_path = device->mount_path();
|
||||||
|
|
|
@ -32,6 +32,7 @@ class VirtualFileSystem {
|
||||||
|
|
||||||
bool RegisterSymbolicLink(std::string path, std::string target);
|
bool RegisterSymbolicLink(std::string path, std::string target);
|
||||||
bool UnregisterSymbolicLink(std::string path);
|
bool UnregisterSymbolicLink(std::string path);
|
||||||
|
bool IsSymbolicLink(const std::string& path);
|
||||||
|
|
||||||
Entry* ResolvePath(std::string path);
|
Entry* ResolvePath(std::string path);
|
||||||
Entry* ResolveBasePath(std::string path);
|
Entry* ResolveBasePath(std::string path);
|
||||||
|
|
Loading…
Reference in New Issue