{"id":2243,"date":"2018-08-13T10:00:00","date_gmt":"2018-08-13T08:00:00","guid":{"rendered":"https:\/\/craftcoders.app\/?p=498"},"modified":"2024-08-14T14:27:55","modified_gmt":"2024-08-14T12:27:55","slug":"do-it-yourself-filesystem-with-dokan","status":"publish","type":"post","link":"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/","title":{"rendered":"Do it yourself filesystem with Dokan"},"content":{"rendered":"

What’s up guys?! A week has passed and its time for a new Blogpost. This time I am gonna give you a small introduction to Dokan. You don’t have a clue? Never heard of Dokan before? No problem… I haven’t either. But in the life as a student there comes the moment where one must write his Bachelor thesis. No matter how much you procrastinate. As a part of my thesis, I had to write a filesystem and this is exactly where Dokan came into play to save my ass.<\/p>\n

WHAT IN THE HELL IS DOKAN?!<\/h2>\n

So let’s start from the beginning. As I mentioned before, I had to implement my own Filesystem. Yeah, basically you could write your own filesystem driver. But that would be like writing a compiler to print a simple “Hello World”. But there is a really cool concept which is heavily used in the Linux world. Its called FUSE (Filesystem in Userspace). With FUSE everyone is able to create their own Filesystem without writing a Kernel component. FUSE empowers you to write a Filesystem in the same manner as a user-mode application. So what is Dokan?! Dokan is simply FUSE for Windows. It is as simple as that. You could even use Dokan to run a filesystem which has been written with FUSE under windows<\/a>.<\/p>\n

Okay cool… How does this magic work?!<\/h3>\n

So you are right. Without a kernel component, there is no way to implement a filesystem. But you don’t have to write it, because Dokan did. So Dokan ships with two components: (1) dokan1.sys alias “Dokan File System Driver” (2) dokan1.dll which is used in a “Filesystem Application”. So take a look at the picture below<\/p>\n

\"\"<\/p>\n

First, a random Application is running. It could be Word, Visual Studio, IntelliJ or your web browser rendering a website that is trying to write a virus into a file ?. Let’s assume it is the web browser. If the web browser tries to write some content x to a file y its gonna fire a I\/O-request.
\nThis I\/O-request is processed by the Windows I\/O Subsystem<\/em>. Note that by passing the I\/O-request to the Windows I\/O Subsystem<\/em> we leave the user mode and enter the kernel mode of Windows (this is 1 in the picture above).<\/p>\n

Secondly, the Windows I\/O Subsystem<\/em> will delegate the I\/O-request to a Driver responsible for the filesystem. In our case that would be the Dokan File System Driver<\/em>. Which is dokan1.sys<\/strong>. Please note that we did not write any code for that driver, it just needs to be installed (this is 2 in the picture above).<\/p>\n

Third, our Filesystem Application<\/em> which has registered itself in the Dokan File System Driver<\/em> gets notified about the I\/O-Request. By implementing the interface which comes in the dokan1.dll<\/strong>, our Filesystem Application<\/em> is now responsible for computing the I\/O-Request. Whatever has to be done needs to be done by our Filesystem Application<\/em>. And as you might already guess: Yes this is the part we need to write! The Filesystem Application<\/em> than invokes a callback function and the Dokan File System Driver<\/em> is back in line (this is 3-4 in the picture).<\/p>\n

Last but not least, the Dokan File System Driver<\/em> receives the I\/O-Response created by our Filesystem Application<\/em> and invokes the callback routine of the Windows I\/O Subsystem<\/em>. The Windows I\/O Subsystem<\/em> than forwards the result to the application which created the I\/O-Request. In our case the Web browser with the porno site (this is 5-6 in the picture).<\/p>\n

Just do it! Writing a simple Filesystem<\/h2>\n

Scope<\/h2>\n

Okay, we are actually not going to implement a complete Filesystem ?. That would be too much for a blog post. We are doing something simple. Let’s create a Filesystem that contains a fake file which can be read with a editor.<\/p>\n

Warmup: Preparations<\/h2>\n

As I already mentioned before, we need to install the Dokan File System Driver<\/em>. It is used as a proxy for our Filesystem Application<\/em>. You can get the latest Version here<\/a>.
\nAs soon as we have the Dokan File System Driver installed, we can create a blank C# Console Application. Please note that you could also use Dokan with
other languages<\/a>. As always, you can find my solution on GitHub<\/a>. After we’ve created the Console Application, which will be our Filesystem Application<\/em>, we need to add the Dokan library (dokan1.dll). Luckily there is a NuGet package<\/a>.
\nEverything settled? Let the game begin!<\/p>\n

Mount the FS<\/h2>\n

First of all, we need to implement the IDokanOperations from the dokan1.dll. Since this is for learning purposes I didn’t create a second class. So everything is in one class. In the Main()-Method I create a new instance of the class and mount the Filesystem.<\/p>\n

static void Main(string[] args)\r\n{\r\n    var m = new StupidFS();\r\n    \/\/ mounting point, dokan options, num of threads\r\n    m.Mount(\"s:\\\\\", DokanOptions.DebugMode, 5);\r\n}\r\n<\/code><\/pre>\n

1..2..3.. and it crashed! What happened? As you can see from the Console output, several I\/O-request failed. First, the GetVolumeInformation-Operation failed and then the Mounted-Operation. They failed because we did not implement them yet. But it’s simple: in the GetVolumeInformation-Request we just need to provide some information for the OS. Basically, this is just some Meta information for our filesystem. Like its name, how long a path can get and which feature it supports. Let’s implement it:<\/p>\n

[...]\r\n\r\npublic NtStatus GetVolumeInformation(...)\r\n{\r\n       volumeLabel = \"CraftCode Crew\";\r\n       features = FileSystemFeatures.None;\r\n       fileSystemName = \"CCCFS\";\r\n       maximumComponentLength = 256;\r\n\r\n       return DokanResult.Success;\r\n}\r\n\r\n[...] \r\n\r\npublic NtStatus Mounted(DokanFileInfo info)\r\n{\r\n       return DokanResult.Success;\r\n}\r\n<\/code><\/pre>\n

But it won’t work yet. We also need to “implement” the CreateFile-Methode:<\/p>\n

public NtStatus CreateFile(...)\r\n{\r\n      return DokanResult.Success;\r\n}\r\n<\/code><\/pre>\n

Did you notice how every method returns a NtStatus? This status indicates wherever a request has failed (and why) or succeeded. You might wonder why we need to return a Success in the CreateFile-Methode for mounting the filesystem. As soon as we mount the filesystem, it tries to create some fileproxis. If we throw an exception, our filesystem ends up in a bad state.<\/p>\n

Faking a file<\/h2>\n

Whenever the filesystem has to list files there a two possible request: FindFilesWithPattern and FindFiles. Luckily, we just need to implement one and suppress the other one. We are going to implement the FindFiles-Methode. Therefore we will return a DokanResult.NotImplemented in FindFilesWithPattern, so whenever the filesystem gets this request it will be rerouted to FindFiles.
\nOne of the parameters in FindFiles is a list of FileInformation objects. We are just going to fake one item and add it to a list which will be set to the parameter files.<\/p>\n

public NtStatus FindFilesWithPattern(...)\r\n{\r\n   files = null;\r\n\r\n   return DokanResult.NotImplemented;\r\n}\r\n\r\npublic NtStatus FindFiles(...)\r\n{\r\n   var  fileInfo = new FileInformation\r\n   {\r\n         FileName = \"carftCodeCrew.txt\",\r\n         CreationTime = DateTime.Now,\r\n         LastAccessTime = DateTime.Now,\r\n         LastWriteTime = DateTime.Now,\r\n         Length =  FileContent.Length * 8,\r\n   };\r\n\r\n   files = new List<FileInformation> {fileInfo};\r\n\r\n   return DokanResult.Success;\r\n}\r\n<\/code><\/pre>\n

And we did it! Our filesystem now shows one file!
\nDid you notice FileContent? It’s just a global string containing the content of our textfile.<\/p>\n

Reading with the good old Editor<\/h2>\n

Let’s read data from our filesystem! We want to read the string FileContent with the good old Editor. So, first of all, we need to make changes to the CreateFile-Methode. Whenever we need to open a file or dir, the CreateFile-Methode gets invoked. We need to provide the DokanFileInfo object with a context. In case of a read operation, the context is a stream where the data is located. Since we want to read a string, we are going to use a MemoryStream.<\/p>\n

public NtStatus CreateFile(...)\r\n{\r\n     if (fileName.Equals(@\"\\carftCodeCrew.txt\"))\r\n     {\r\n       info.Context = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(FileContent));\r\n     }\r\n\r\n       return DokanResult.Success;\r\n}\r\n<\/code><\/pre>\n

We are close but not quite there. When an application like Editor tries to open a file it also wants to read the meta information of the file. For example, to set the window title. Therefore we need to implement the GetFileInformation-Methode. Since our filesystem just has one file it is really trivial:<\/p>\n

public NtStatus GetFileInformation(...)\r\n{\r\n     fileInfo = new FileInformation\r\n     {\r\n            FileName = \"carftCodeCrew.txt\",\r\n            Attributes = 0,\r\n            CreationTime = DateTime.Now,\r\n            LastAccessTime = DateTime.Now,\r\n            LastWriteTime = DateTime.Now,\r\n            Length =  FileContent.Length * 8,\r\n     };\r\n\r\n     return DokanResult.Success;\r\n}\r\n<\/code><\/pre>\n

Now we are really close ? We just need to implement the ReadFile-Methode(). In this method, we get the Stream from the DokanFileInfo.Context and then read the bytes that have been requested. It is really as simple as this.<\/p>\n

public NtStatus ReadFile(...)\r\n{\r\n      bytesRead = 0;\r\n\r\n      if (info.Context is MemoryStream stream)\r\n      {\r\n          stream.Position = offset;\r\n          bytesRead = stream.Read(buffer, 0, buffer.Length);\r\n      }\r\n\r\n      return DokanResult.Success;\r\n}\r\n<\/code><\/pre>\n

The lovely CraftCodeCrewFS<\/h2>\n

\"\"<\/p>\n","protected":false},"excerpt":{"rendered":"

What’s up guys?! A week has passed and its time for a new Blogpost. This time I am gonna give you a small introduction to Dokan. You don’t have a clue? Never heard of Dokan before? No problem… I haven’t either. But in the life as a student there comes the moment where one must write his Bachelor thesis. No … Read More<\/a><\/p>\n","protected":false},"author":8,"featured_media":2350,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[110,109,143],"tags":[],"acf":[],"yoast_head":"\nDo it yourself filesystem with Dokan - CraftCoders.app<\/title>\n<meta name=\"description\" content=\"How to implement a simple filesystem with Dokan. By using Dokan every developer is able to create a filesystem that runs in user mode under windows.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Do it yourself filesystem with Dokan - CraftCoders.app\" \/>\n<meta property=\"og:description\" content=\"How to implement a simple filesystem with Dokan. By using Dokan every developer is able to create a filesystem that runs in user mode under windows.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/\" \/>\n<meta property=\"og:site_name\" content=\"CraftCoders.app\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-13T08:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-08-14T12:27:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/craftcoders.app\/wp-content\/uploads\/2018\/08\/Bildschirmfoto-2019-02-03-um-17.38.26-768x639-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"768\" \/>\n\t<meta property=\"og:image:height\" content=\"639\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Cem Freimoser\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Cem Freimoser\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/\",\"url\":\"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/\",\"name\":\"Do it yourself filesystem with Dokan - CraftCoders.app\",\"isPartOf\":{\"@id\":\"https:\/\/craftcoders.app\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/craftcoders.app\/wp-content\/uploads\/2018\/08\/Bildschirmfoto-2019-02-03-um-17.38.26-768x639-1.png\",\"datePublished\":\"2018-08-13T08:00:00+00:00\",\"dateModified\":\"2024-08-14T12:27:55+00:00\",\"author\":{\"@id\":\"https:\/\/craftcoders.app\/#\/schema\/person\/1de3ca624627af12a8288c134309e6c4\"},\"description\":\"How to implement a simple filesystem with Dokan. By using Dokan every developer is able to create a filesystem that runs in user mode under windows.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/#primaryimage\",\"url\":\"https:\/\/craftcoders.app\/wp-content\/uploads\/2018\/08\/Bildschirmfoto-2019-02-03-um-17.38.26-768x639-1.png\",\"contentUrl\":\"https:\/\/craftcoders.app\/wp-content\/uploads\/2018\/08\/Bildschirmfoto-2019-02-03-um-17.38.26-768x639-1.png\",\"width\":768,\"height\":639},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/craftcoders.app\/#website\",\"url\":\"https:\/\/craftcoders.app\/\",\"name\":\"CraftCoders.app\",\"description\":\"Jira and Confluence apps\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/craftcoders.app\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/craftcoders.app\/#\/schema\/person\/1de3ca624627af12a8288c134309e6c4\",\"name\":\"Cem Freimoser\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/craftcoders.app\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6fcc13f5b3fd0bb1d5c3801174819538?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6fcc13f5b3fd0bb1d5c3801174819538?s=96&d=mm&r=g\",\"caption\":\"Cem Freimoser\"},\"url\":\"https:\/\/craftcoders.app\/author\/cem\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Do it yourself filesystem with Dokan - CraftCoders.app","description":"How to implement a simple filesystem with Dokan. By using Dokan every developer is able to create a filesystem that runs in user mode under windows.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/","og_locale":"en_US","og_type":"article","og_title":"Do it yourself filesystem with Dokan - CraftCoders.app","og_description":"How to implement a simple filesystem with Dokan. By using Dokan every developer is able to create a filesystem that runs in user mode under windows.","og_url":"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/","og_site_name":"CraftCoders.app","article_published_time":"2018-08-13T08:00:00+00:00","article_modified_time":"2024-08-14T12:27:55+00:00","og_image":[{"width":768,"height":639,"url":"https:\/\/craftcoders.app\/wp-content\/uploads\/2018\/08\/Bildschirmfoto-2019-02-03-um-17.38.26-768x639-1.png","type":"image\/png"}],"author":"Cem Freimoser","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Cem Freimoser","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/","url":"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/","name":"Do it yourself filesystem with Dokan - CraftCoders.app","isPartOf":{"@id":"https:\/\/craftcoders.app\/#website"},"primaryImageOfPage":{"@id":"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/#primaryimage"},"image":{"@id":"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/#primaryimage"},"thumbnailUrl":"https:\/\/craftcoders.app\/wp-content\/uploads\/2018\/08\/Bildschirmfoto-2019-02-03-um-17.38.26-768x639-1.png","datePublished":"2018-08-13T08:00:00+00:00","dateModified":"2024-08-14T12:27:55+00:00","author":{"@id":"https:\/\/craftcoders.app\/#\/schema\/person\/1de3ca624627af12a8288c134309e6c4"},"description":"How to implement a simple filesystem with Dokan. By using Dokan every developer is able to create a filesystem that runs in user mode under windows.","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/craftcoders.app\/do-it-yourself-filesystem-with-dokan\/#primaryimage","url":"https:\/\/craftcoders.app\/wp-content\/uploads\/2018\/08\/Bildschirmfoto-2019-02-03-um-17.38.26-768x639-1.png","contentUrl":"https:\/\/craftcoders.app\/wp-content\/uploads\/2018\/08\/Bildschirmfoto-2019-02-03-um-17.38.26-768x639-1.png","width":768,"height":639},{"@type":"WebSite","@id":"https:\/\/craftcoders.app\/#website","url":"https:\/\/craftcoders.app\/","name":"CraftCoders.app","description":"Jira and Confluence apps","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/craftcoders.app\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/craftcoders.app\/#\/schema\/person\/1de3ca624627af12a8288c134309e6c4","name":"Cem Freimoser","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/craftcoders.app\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6fcc13f5b3fd0bb1d5c3801174819538?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6fcc13f5b3fd0bb1d5c3801174819538?s=96&d=mm&r=g","caption":"Cem Freimoser"},"url":"https:\/\/craftcoders.app\/author\/cem\/"}]}},"_links":{"self":[{"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/posts\/2243"}],"collection":[{"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/comments?post=2243"}],"version-history":[{"count":3,"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/posts\/2243\/revisions"}],"predecessor-version":[{"id":2352,"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/posts\/2243\/revisions\/2352"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/media\/2350"}],"wp:attachment":[{"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/media?parent=2243"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/categories?post=2243"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/craftcoders.app\/wp-json\/wp\/v2\/tags?post=2243"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}