dokan-ruby 0.0.1-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.rdoc +39 -0
- data/Rakefile +63 -0
- data/VERSION +1 -0
- data/dokan-ruby.gemspec +66 -0
- data/ext/dokan-ruby-0.1.5.1229/API.txt +45 -0
- data/ext/dokan-ruby-0.1.5.1229/dokan_lib.c +1987 -0
- data/ext/dokan-ruby-0.1.5.1229/dokan_lib.so +0 -0
- data/ext/dokan-ruby-0.1.5.1229/extconf.rb +11 -0
- data/ext/dokan-ruby-0.1.5.1229/lib/dokanfs.rb +390 -0
- data/ext/dokan-ruby-0.1.5.1229/license.txt +19 -0
- data/ext/dokan-ruby-0.1.5.1229/list.h +144 -0
- data/ext/dokan-ruby-0.1.5.1229/readme.ja.txt +66 -0
- data/ext/dokan-ruby-0.1.5.1229/readme.txt +70 -0
- data/ext/dokan-ruby-0.1.5.1229/sample/hello.rb +39 -0
- data/ext/dokan-ruby-0.1.5.1229/sample/mirror.rb +178 -0
- data/ext/dokan-ruby-0.1.5.1229/sample/rssfs.rb +52 -0
- data/ext/dokan-ruby-0.1.5.1229/sample/sshfs.rb +163 -0
- data/ext/dokan-ruby-0.1.5.1229/sample/test.rb +115 -0
- data/lib/dokan-ruby.rb +1 -0
- data/test/dokan-ruby_test.rb +29 -0
- data/test/test_helper.rb +11 -0
- metadata +90 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 AncientLeGrey
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
= dokan-ruby
|
2
|
+
|
3
|
+
This is as wrapper-gem for dokan ruby bindings by Hiroki Asakawa.
|
4
|
+
You can download the original souce from http://dokan-dev.net/en/download/#ruby.
|
5
|
+
|
6
|
+
To run this gem you need dokan library installed.
|
7
|
+
|
8
|
+
See the original README and LICENSE at
|
9
|
+
* ext\dokan-ruby-0.1.5.1229\readme.txt
|
10
|
+
* ext\dokan-ruby-0.1.5.1229\license.txt
|
11
|
+
|
12
|
+
== What is Dokan Ruby Binding
|
13
|
+
|
14
|
+
This program is a Ruby binding of Dokan that is a user mode file
|
15
|
+
system for Windows. Using this program, you can make a file system
|
16
|
+
in Ruby language.
|
17
|
+
Ruby extension to write a windows file system.
|
18
|
+
|
19
|
+
== Howto
|
20
|
+
|
21
|
+
1. Install dokan library. You can find it here: http://dokan-dev.net/en/download/
|
22
|
+
2. Install this gem (gem install dokan-ruby)
|
23
|
+
3. Run the samples unter ext\dokan-ruby-0.1.5.1229\samples to get a feeling ho things work
|
24
|
+
4. Implement your own cool filsystem und mount it
|
25
|
+
|
26
|
+
== Note on Patches/Pull Requests
|
27
|
+
|
28
|
+
* Fork the project.
|
29
|
+
* Make your feature addition or bug fix.
|
30
|
+
* Add tests for it. This is important so I don't break it in a
|
31
|
+
future version unintentionally.
|
32
|
+
* Commit, do not mess with rakefile, version, or history.
|
33
|
+
(if you want to have your own version, that is fine but
|
34
|
+
bump version in a commit by itself I can ignore when I pull)
|
35
|
+
* Send me a pull request. Bonus points for topic branches.
|
36
|
+
|
37
|
+
== Copyright
|
38
|
+
|
39
|
+
Copyright (c) 2009 AncientLeGrey. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
# Source: http://dokan-dev.net/en/download/#ruby
|
5
|
+
DOKAN_RUBY_EXT = "dokan-ruby-0.1.5.1229"
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gem|
|
10
|
+
gem.name = "dokan-ruby"
|
11
|
+
gem.platform = 'mswin32'
|
12
|
+
gem.summary = %q{Ruby extension to write a windows file system (depending on Dokan library)}
|
13
|
+
gem.description = %q{Dokan ist a "file system in userspace" driver for Win32. With dokan-ruby bindings, you can implement your own filesystem in Ruby!}
|
14
|
+
gem.email = "greyhound@freenet.de"
|
15
|
+
gem.homepage = "http://github.com/AncientLeGrey/dokan-ruby"
|
16
|
+
gem.authors = ["AncientLeGrey"]
|
17
|
+
gem.files = FileList["[A-Z]*", "{lib,test,ext,sample}/**/*"]
|
18
|
+
gem.require_paths = ["lib", "ext/#{DOKAN_RUBY_EXT}", "ext/#{DOKAN_RUBY_EXT}/lib"]
|
19
|
+
gem.rdoc_options = ["--exclude", "dokan_lib.c"]
|
20
|
+
gem.add_development_dependency "shoulda"
|
21
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
Rake::TestTask.new(:test) do |test|
|
29
|
+
test.libs << 'lib' << 'test'
|
30
|
+
test.pattern = 'test/**/*_test.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/*_test.rb'
|
39
|
+
test.verbose = true
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
task :rcov do
|
43
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
task :test => :check_dependencies
|
48
|
+
|
49
|
+
task :default => :test
|
50
|
+
|
51
|
+
require 'rake/rdoctask'
|
52
|
+
Rake::RDocTask.new do |rdoc|
|
53
|
+
if File.exist?('VERSION')
|
54
|
+
version = File.read('VERSION')
|
55
|
+
else
|
56
|
+
version = ""
|
57
|
+
end
|
58
|
+
|
59
|
+
rdoc.rdoc_dir = 'rdoc'
|
60
|
+
rdoc.title = "dokan-ruby #{version}"
|
61
|
+
rdoc.rdoc_files.include('README*')
|
62
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
63
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/dokan-ruby.gemspec
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{dokan-ruby}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
s.platform = %q{mswin32}
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.authors = ["AncientLeGrey"]
|
13
|
+
s.date = %q{2009-10-16}
|
14
|
+
s.description = %q{Dokan ist a "file system in userspace" driver for Win32. With dokan-ruby bindings, you can implement your own filesystem in Ruby!}
|
15
|
+
s.email = %q{greyhound@freenet.de}
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
"LICENSE",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"dokan-ruby.gemspec",
|
26
|
+
"ext/dokan-ruby-0.1.5.1229/API.txt",
|
27
|
+
"ext/dokan-ruby-0.1.5.1229/dokan_lib.c",
|
28
|
+
"ext/dokan-ruby-0.1.5.1229/dokan_lib.so",
|
29
|
+
"ext/dokan-ruby-0.1.5.1229/extconf.rb",
|
30
|
+
"ext/dokan-ruby-0.1.5.1229/lib/dokanfs.rb",
|
31
|
+
"ext/dokan-ruby-0.1.5.1229/license.txt",
|
32
|
+
"ext/dokan-ruby-0.1.5.1229/list.h",
|
33
|
+
"ext/dokan-ruby-0.1.5.1229/readme.ja.txt",
|
34
|
+
"ext/dokan-ruby-0.1.5.1229/readme.txt",
|
35
|
+
"ext/dokan-ruby-0.1.5.1229/sample/hello.rb",
|
36
|
+
"ext/dokan-ruby-0.1.5.1229/sample/mirror.rb",
|
37
|
+
"ext/dokan-ruby-0.1.5.1229/sample/rssfs.rb",
|
38
|
+
"ext/dokan-ruby-0.1.5.1229/sample/sshfs.rb",
|
39
|
+
"ext/dokan-ruby-0.1.5.1229/sample/test.rb",
|
40
|
+
"lib/dokan-ruby.rb",
|
41
|
+
"test/dokan-ruby_test.rb",
|
42
|
+
"test/test_helper.rb"
|
43
|
+
]
|
44
|
+
s.homepage = %q{http://github.com/AncientLeGrey/dokan-ruby}
|
45
|
+
s.rdoc_options = ["--exclude", "dokan_lib.c"]
|
46
|
+
s.require_paths = ["lib", "ext/dokan-ruby-0.1.5.1229", "ext/dokan-ruby-0.1.5.1229/lib"]
|
47
|
+
s.rubygems_version = %q{1.3.5}
|
48
|
+
s.summary = %q{Ruby extension to write a windows file system (depending on Dokan library)}
|
49
|
+
s.test_files = [
|
50
|
+
"test/dokan-ruby_test.rb",
|
51
|
+
"test/test_helper.rb"
|
52
|
+
]
|
53
|
+
|
54
|
+
if s.respond_to? :specification_version then
|
55
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
62
|
+
end
|
63
|
+
else
|
64
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
open(path, context)
|
3
|
+
|
4
|
+
create(path, context)
|
5
|
+
|
6
|
+
truncate(path, context)
|
7
|
+
|
8
|
+
opendir(path, context)
|
9
|
+
|
10
|
+
mkdir(path, context)
|
11
|
+
|
12
|
+
cleanup(path, context)
|
13
|
+
|
14
|
+
close(path, context)
|
15
|
+
|
16
|
+
read(path, offset, length, context)
|
17
|
+
|
18
|
+
write(path, offset, data, context)
|
19
|
+
|
20
|
+
flush(path, context)
|
21
|
+
|
22
|
+
stat(path, context)
|
23
|
+
[size, attr, ctime, atime, mtime]
|
24
|
+
|
25
|
+
# not implemented
|
26
|
+
# readdira(path, context)
|
27
|
+
# [ [name, size, attr, ctime, atime, mtime], [], ]
|
28
|
+
|
29
|
+
readdir(path, context)
|
30
|
+
[name1, name2, name3...]
|
31
|
+
|
32
|
+
setattr(path, attr, context)
|
33
|
+
|
34
|
+
utime(path, ctime, atime, mtime, context)
|
35
|
+
|
36
|
+
remove(path, context)
|
37
|
+
|
38
|
+
rename(path, newpath, context)
|
39
|
+
|
40
|
+
rmdir(path, context)
|
41
|
+
|
42
|
+
unmount(path, context)
|
43
|
+
|
44
|
+
|
45
|
+
|
@@ -0,0 +1,1987 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "dokan.h"
|
3
|
+
#include "list.h"
|
4
|
+
#include <locale.h>
|
5
|
+
|
6
|
+
#pragma comment(lib, "dokan.lib")
|
7
|
+
|
8
|
+
#define _UNICODE
|
9
|
+
|
10
|
+
|
11
|
+
#define CREATE_FILE_F 1
|
12
|
+
#define OPEN_DIRECTORY_F 2
|
13
|
+
#define CREATE_DIRECTORY_F 3
|
14
|
+
#define CLOSE_FILE_F 4
|
15
|
+
#define READ_FILE_F 5
|
16
|
+
#define WRITE_FILE_F 6
|
17
|
+
#define GET_FILE_INFO_F 7
|
18
|
+
#define FIND_FILES_F 8
|
19
|
+
#define SET_FILE_ATTR_F 9
|
20
|
+
#define SET_FILE_TIME_F 10
|
21
|
+
#define DELETE_FILE_F 11
|
22
|
+
#define DELETE_DIRECTORY_F 12
|
23
|
+
//#define SET_FILE_POINTER_F 13
|
24
|
+
#define MOVE_FILE_F 14
|
25
|
+
#define SET_END_OF_FILE_F 15
|
26
|
+
#define LOCK_FILE_F 16
|
27
|
+
#define UNLOCK_FILE_F 17
|
28
|
+
#define UNMOUNT_F 18
|
29
|
+
#define CLEANUP_F 19
|
30
|
+
#define FLUSH_F 20
|
31
|
+
|
32
|
+
static VALUE g_DokanRoot = Qnil;
|
33
|
+
static VALUE g_cDokan = Qnil;
|
34
|
+
static VALUE g_cFileInfo = Qnil;
|
35
|
+
|
36
|
+
static LIST_ENTRY g_EventQueue;
|
37
|
+
static HANDLE g_DispatchEvent;
|
38
|
+
static HANDLE g_DispatchMutex;
|
39
|
+
|
40
|
+
static BOOL g_Debug = FALSE;
|
41
|
+
|
42
|
+
/*
|
43
|
+
open(path, fileinfo)
|
44
|
+
|
45
|
+
create(path, fileinfo)
|
46
|
+
|
47
|
+
truncate(path, offset, fileinfo)
|
48
|
+
|
49
|
+
opendir(path, fileinfo)
|
50
|
+
|
51
|
+
mkdir(path, fileinfo)
|
52
|
+
|
53
|
+
close(path, fileinfo)
|
54
|
+
|
55
|
+
cleanup(path, fileinfo)
|
56
|
+
|
57
|
+
read(path, offset, length, fileinfo)
|
58
|
+
|
59
|
+
write(path, offset, data, fileinfo)
|
60
|
+
|
61
|
+
flush(path, fileinfo)
|
62
|
+
|
63
|
+
stat(path, fileinfo)
|
64
|
+
[size, attr, ctime, atime, mtime]
|
65
|
+
|
66
|
+
readdira(path, fileinfo)
|
67
|
+
[ [name, size, attr, ctime, atime, mtime], [], ]
|
68
|
+
|
69
|
+
readdir(path, fileinfo)
|
70
|
+
[name1, name2, name3...]
|
71
|
+
|
72
|
+
setattr(path, attr, fileinfo)
|
73
|
+
|
74
|
+
utime(path, ctime, atime, mtime, fileinfo)
|
75
|
+
|
76
|
+
remove(path, fileinfo)
|
77
|
+
|
78
|
+
rename(path, newpath, fileinfo)
|
79
|
+
|
80
|
+
rmdir(path, fileinfo)
|
81
|
+
|
82
|
+
lock(path, offset, length, fileinfo)
|
83
|
+
|
84
|
+
unlock(path, offset, length, fileinfo)
|
85
|
+
|
86
|
+
unmount(path, fileinfo)
|
87
|
+
*/
|
88
|
+
|
89
|
+
|
90
|
+
static int
|
91
|
+
DR_DebugPrint(
|
92
|
+
const wchar_t *format, ...)
|
93
|
+
{
|
94
|
+
int r = 0;
|
95
|
+
va_list va;
|
96
|
+
va_start(va, format);
|
97
|
+
if (g_Debug)
|
98
|
+
r = vfwprintf(stderr, format, va);
|
99
|
+
va_end(va);
|
100
|
+
return r;
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
static VALUE
|
105
|
+
DR_FileInfo_directory_p(
|
106
|
+
VALUE self)
|
107
|
+
{
|
108
|
+
return rb_iv_get(self, "@is_directory");
|
109
|
+
}
|
110
|
+
|
111
|
+
|
112
|
+
static VALUE
|
113
|
+
DR_FileInfo_process_id(
|
114
|
+
VALUE self)
|
115
|
+
{
|
116
|
+
return rb_iv_get(self, "@process_id");
|
117
|
+
}
|
118
|
+
|
119
|
+
static VALUE
|
120
|
+
DR_FileInfo_context(
|
121
|
+
VALUE self)
|
122
|
+
{
|
123
|
+
return rb_iv_get(self, "@context");
|
124
|
+
}
|
125
|
+
|
126
|
+
static VALUE
|
127
|
+
DR_FileInfo_set_context(
|
128
|
+
VALUE self,
|
129
|
+
VALUE context)
|
130
|
+
{
|
131
|
+
VALUE ary;
|
132
|
+
VALUE old = rb_iv_get(self, "@context");
|
133
|
+
if (old != Qnil)
|
134
|
+
rb_gc_unregister_address(&old);
|
135
|
+
|
136
|
+
rb_iv_set(self, "@context", context);
|
137
|
+
|
138
|
+
// to prevent from gc, register the context as global object
|
139
|
+
rb_gc_register_address(&context);
|
140
|
+
//ary = rb_gv_get("$dokan_context");
|
141
|
+
//rb_ary_push(ary, context);
|
142
|
+
|
143
|
+
return self;
|
144
|
+
}
|
145
|
+
|
146
|
+
|
147
|
+
static VOID
|
148
|
+
DR_SetFileContext(
|
149
|
+
PDOKAN_FILE_INFO DokanFileInfo,
|
150
|
+
VALUE FileInfo)
|
151
|
+
{
|
152
|
+
VALUE context = rb_iv_get(FileInfo, "@context");
|
153
|
+
if (context != Qnil)
|
154
|
+
DokanFileInfo->Context = (ULONG64)context;
|
155
|
+
}
|
156
|
+
|
157
|
+
|
158
|
+
static VOID
|
159
|
+
DR_ReleaseFileContext(
|
160
|
+
VALUE FileInfo)
|
161
|
+
{
|
162
|
+
VALUE context = rb_iv_get(FileInfo, "@context");
|
163
|
+
if (context != Qnil)
|
164
|
+
rb_gc_unregister_address(&context);
|
165
|
+
}
|
166
|
+
|
167
|
+
|
168
|
+
static VOID
|
169
|
+
DR_DefineFileInfoClass()
|
170
|
+
{
|
171
|
+
g_cFileInfo = rb_define_class_under(g_cDokan, "FileInfo", rb_cObject);
|
172
|
+
|
173
|
+
rb_define_method(g_cFileInfo, "directory?", DR_FileInfo_directory_p, 0);
|
174
|
+
rb_define_method(g_cFileInfo, "process_id", DR_FileInfo_process_id, 0);
|
175
|
+
rb_define_method(g_cFileInfo, "context", DR_FileInfo_context, 0);
|
176
|
+
rb_define_method(g_cFileInfo, "context=", DR_FileInfo_set_context, 1);
|
177
|
+
}
|
178
|
+
|
179
|
+
|
180
|
+
static VALUE
|
181
|
+
DR_GetFileInfo(
|
182
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
183
|
+
{
|
184
|
+
VALUE info = rb_class_new_instance(0, NULL, g_cFileInfo);
|
185
|
+
|
186
|
+
rb_iv_set(info, "@is_directory", DokanFileInfo->IsDirectory ? Qtrue : Qfalse);
|
187
|
+
rb_iv_set(info, "@process_id", ULONG2NUM(DokanFileInfo->ProcessId));
|
188
|
+
|
189
|
+
rb_iv_set(info, "@context",
|
190
|
+
DokanFileInfo->Context ? (VALUE)DokanFileInfo->Context : Qnil);
|
191
|
+
return info;
|
192
|
+
}
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
static VALUE
|
197
|
+
DR_GetFileName(
|
198
|
+
LPCWSTR FileName)
|
199
|
+
{
|
200
|
+
wchar_t name0[MAX_PATH];
|
201
|
+
char name[MAX_PATH];
|
202
|
+
VALUE file;
|
203
|
+
int i;
|
204
|
+
|
205
|
+
wcscpy(name0, FileName);
|
206
|
+
for (i=0; i<wcslen(name0); ++i) {
|
207
|
+
if (name0[i] == L'\\')
|
208
|
+
name0[i] = L'/';
|
209
|
+
}
|
210
|
+
|
211
|
+
wcstombs(name, name0, sizeof(name));
|
212
|
+
file = rb_str_new2(name);
|
213
|
+
return file;
|
214
|
+
}
|
215
|
+
|
216
|
+
|
217
|
+
|
218
|
+
// TODO: this is not good error handling
|
219
|
+
// CreateFile always return FILE_NOT_FOUND when error occured
|
220
|
+
|
221
|
+
static int
|
222
|
+
DR_CreateFile(
|
223
|
+
LPCWSTR FileName,
|
224
|
+
DWORD AccessMode,
|
225
|
+
DWORD ShareMode,
|
226
|
+
DWORD CreationDisposition,
|
227
|
+
DWORD FlagsAndAttributes,
|
228
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
229
|
+
{
|
230
|
+
VALUE file = DR_GetFileName(FileName);
|
231
|
+
VALUE fileinfo = DR_GetFileInfo(DokanFileInfo);
|
232
|
+
VALUE ret;
|
233
|
+
|
234
|
+
DR_DebugPrint(L"CreateFile %ws\n", FileName);
|
235
|
+
|
236
|
+
|
237
|
+
switch (CreationDisposition) {
|
238
|
+
case CREATE_NEW:
|
239
|
+
// Creates a new file. The function fails if the specified
|
240
|
+
// file already exists.
|
241
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("create"), 2, file, fileinfo);
|
242
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
243
|
+
return RTEST(ret) ? 0 : -ERROR_FILE_NOT_FOUND;
|
244
|
+
|
245
|
+
case CREATE_ALWAYS:
|
246
|
+
// Creates a new file. If the file exists, the function overwrites
|
247
|
+
// the file and clears the existing attributes.
|
248
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("create"), 2, file, fileinfo);
|
249
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
250
|
+
return RTEST(ret) ? 0 : -ERROR_FILE_NOT_FOUND;
|
251
|
+
|
252
|
+
case OPEN_EXISTING:
|
253
|
+
// Opens the file. The function fails if the file does not exist.
|
254
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("open"), 2, file, fileinfo);
|
255
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
256
|
+
return RTEST(ret) ? 0 : -ERROR_FILE_NOT_FOUND;
|
257
|
+
|
258
|
+
case OPEN_ALWAYS:
|
259
|
+
// Opens the file, if it exists. If the file does not exist,
|
260
|
+
// the function creates the file as if dwCreationDisposition were CREATE_NEW.
|
261
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("create"), 2, file, fileinfo);
|
262
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
263
|
+
return RTEST(ret) ? 0 : -ERROR_FILE_NOT_FOUND;
|
264
|
+
|
265
|
+
case TRUNCATE_EXISTING:
|
266
|
+
// Opens the file. Once opened, the file is truncated so that its size
|
267
|
+
// is zero bytes. The calling process must open the file with at least
|
268
|
+
// GENERIC_WRITE access. The function fails if the file does not exist.
|
269
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("open"), 2, file, fileinfo);
|
270
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
271
|
+
|
272
|
+
if (RTEST(ret))
|
273
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("truncate"), 3, file, INT2FIX(0), fileinfo);
|
274
|
+
|
275
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
276
|
+
return RTEST(ret) ? 0 : -ERROR_FILE_NOT_FOUND;
|
277
|
+
default:
|
278
|
+
fprintf(stderr, "unknown CreationDisposition %d\n", CreationDisposition);
|
279
|
+
}
|
280
|
+
return -ERROR_FILE_NOT_FOUND;
|
281
|
+
}
|
282
|
+
|
283
|
+
|
284
|
+
|
285
|
+
|
286
|
+
static int
|
287
|
+
DR_CreateDirectory(
|
288
|
+
LPCWSTR FileName,
|
289
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
290
|
+
{
|
291
|
+
VALUE file = DR_GetFileName(FileName);
|
292
|
+
VALUE fileinfo = DR_GetFileInfo(DokanFileInfo);
|
293
|
+
VALUE ret;
|
294
|
+
|
295
|
+
DR_DebugPrint(L"CreateDirectory %ws\n", FileName);
|
296
|
+
|
297
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("mkdir"), 2, file, fileinfo);
|
298
|
+
|
299
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
300
|
+
|
301
|
+
return RTEST(ret) ? 0 : -ERROR_FILE_NOT_FOUND;
|
302
|
+
}
|
303
|
+
|
304
|
+
|
305
|
+
|
306
|
+
static int
|
307
|
+
DR_OpenDirectory(
|
308
|
+
LPCWSTR FileName,
|
309
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
310
|
+
{
|
311
|
+
VALUE file = DR_GetFileName(FileName);
|
312
|
+
VALUE fileinfo = DR_GetFileInfo(DokanFileInfo);
|
313
|
+
VALUE ret;
|
314
|
+
|
315
|
+
DR_DebugPrint(L"OpenDirectory %ws\n", FileName);
|
316
|
+
|
317
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("opendir"), 2, file, fileinfo);
|
318
|
+
|
319
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
320
|
+
|
321
|
+
return RTEST(ret) ? 0 : -ERROR_FILE_NOT_FOUND;
|
322
|
+
}
|
323
|
+
|
324
|
+
|
325
|
+
static int
|
326
|
+
DR_CloseFile(
|
327
|
+
LPCWSTR FileName,
|
328
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
329
|
+
{
|
330
|
+
VALUE file = DR_GetFileName(FileName);
|
331
|
+
VALUE fileinfo = DR_GetFileInfo(DokanFileInfo);
|
332
|
+
VALUE ret;
|
333
|
+
|
334
|
+
DR_DebugPrint(L"CloseFile %ws\n", FileName);
|
335
|
+
|
336
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("close"), 2, file, fileinfo);
|
337
|
+
|
338
|
+
DR_ReleaseFileContext(fileinfo);
|
339
|
+
|
340
|
+
return RTEST(ret) ? 0 : -1;
|
341
|
+
}
|
342
|
+
|
343
|
+
|
344
|
+
static int
|
345
|
+
DR_Cleanup(
|
346
|
+
LPCWSTR FileName,
|
347
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
348
|
+
{
|
349
|
+
VALUE file = DR_GetFileName(FileName);
|
350
|
+
VALUE fileinfo = DR_GetFileInfo(DokanFileInfo);
|
351
|
+
VALUE ret;
|
352
|
+
|
353
|
+
DR_DebugPrint(L"Cleanup %ws\n", FileName);
|
354
|
+
|
355
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("cleanup"), 2, file, fileinfo);
|
356
|
+
|
357
|
+
//DR_SetFileContext(DokanFileInfo, fileinfo);
|
358
|
+
|
359
|
+
return RTEST(ret) ? 0 : -1;
|
360
|
+
}
|
361
|
+
|
362
|
+
|
363
|
+
static int
|
364
|
+
DR_ReadFile(
|
365
|
+
LPCWSTR FileName,
|
366
|
+
LPVOID Buffer,
|
367
|
+
DWORD BufferLength,
|
368
|
+
LPDWORD ReadLength,
|
369
|
+
LONGLONG Offset,
|
370
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
371
|
+
{
|
372
|
+
VALUE file, fileinfo, ret;
|
373
|
+
ULONG len;
|
374
|
+
ULONG size;
|
375
|
+
char* str;
|
376
|
+
|
377
|
+
DR_DebugPrint(L"ReadFile %ws\n", FileName);
|
378
|
+
|
379
|
+
file = DR_GetFileName(FileName);
|
380
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
381
|
+
|
382
|
+
ret = rb_funcall(g_DokanRoot,
|
383
|
+
rb_intern("read"),
|
384
|
+
4,
|
385
|
+
file,
|
386
|
+
ULONG2NUM((ULONG)Offset),
|
387
|
+
ULONG2NUM((ULONG)BufferLength),
|
388
|
+
fileinfo);
|
389
|
+
|
390
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
391
|
+
|
392
|
+
if (!RTEST(ret))
|
393
|
+
return -1;
|
394
|
+
|
395
|
+
StringValue(ret);
|
396
|
+
|
397
|
+
len = RSTRING(ret)->len;
|
398
|
+
str = RSTRING(ret)->ptr;
|
399
|
+
|
400
|
+
size = BufferLength < len ? BufferLength : len;
|
401
|
+
|
402
|
+
*ReadLength = size;
|
403
|
+
CopyMemory(Buffer, str, size);
|
404
|
+
|
405
|
+
return 0;
|
406
|
+
}
|
407
|
+
|
408
|
+
|
409
|
+
static int
|
410
|
+
DR_WriteFile(
|
411
|
+
LPCWSTR FileName,
|
412
|
+
LPCVOID Buffer,
|
413
|
+
DWORD NumberOfBytesToWrite,
|
414
|
+
LPDWORD NumberOfBytesWritten,
|
415
|
+
LONGLONG Offset,
|
416
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
417
|
+
{
|
418
|
+
VALUE fileinfo, file;
|
419
|
+
VALUE str, ret;
|
420
|
+
|
421
|
+
DR_DebugPrint(L"WriteFile %ws\n", FileName);
|
422
|
+
|
423
|
+
file = DR_GetFileName(FileName);
|
424
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
425
|
+
|
426
|
+
str = rb_str_new(Buffer, NumberOfBytesToWrite);
|
427
|
+
|
428
|
+
ret = rb_funcall(g_DokanRoot,
|
429
|
+
rb_intern("write"),
|
430
|
+
4,
|
431
|
+
file,
|
432
|
+
ULONG2NUM((ULONG)Offset),
|
433
|
+
str,
|
434
|
+
fileinfo);
|
435
|
+
|
436
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
437
|
+
|
438
|
+
if (!RTEST(ret))
|
439
|
+
return -1;
|
440
|
+
|
441
|
+
*NumberOfBytesWritten = NumberOfBytesToWrite;
|
442
|
+
|
443
|
+
return 0;
|
444
|
+
}
|
445
|
+
|
446
|
+
|
447
|
+
static int
|
448
|
+
DR_Flush(
|
449
|
+
LPCWSTR FileName,
|
450
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
451
|
+
{
|
452
|
+
VALUE file, fileinfo;
|
453
|
+
VALUE ret;
|
454
|
+
|
455
|
+
DR_DebugPrint(L"Flush %ws\n", FileName);
|
456
|
+
|
457
|
+
file = DR_GetFileName(FileName);
|
458
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
459
|
+
|
460
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("flush"), 2, file, fileinfo);
|
461
|
+
|
462
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
463
|
+
|
464
|
+
|
465
|
+
if (!RTEST(ret))
|
466
|
+
return -1;
|
467
|
+
else
|
468
|
+
return 0;
|
469
|
+
}
|
470
|
+
|
471
|
+
|
472
|
+
|
473
|
+
static VOID
|
474
|
+
DR_UnixTimeToFileTime(
|
475
|
+
int Time,
|
476
|
+
LPFILETIME FileTime)
|
477
|
+
{
|
478
|
+
LONGLONG ll;
|
479
|
+
ll = Int32x32To64(Time, 10000000) + 116444736000000000;
|
480
|
+
FileTime->dwLowDateTime = (DWORD)ll;
|
481
|
+
FileTime->dwHighDateTime = ll >> 32;
|
482
|
+
}
|
483
|
+
|
484
|
+
|
485
|
+
static int
|
486
|
+
DR_GetFileInformation(
|
487
|
+
LPCWSTR FileName,
|
488
|
+
LPBY_HANDLE_FILE_INFORMATION HandleFileInformation,
|
489
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
490
|
+
{
|
491
|
+
VALUE file, fileinfo;
|
492
|
+
VALUE ret;
|
493
|
+
|
494
|
+
DR_DebugPrint(L"GetFileInfo %ws\n", FileName);
|
495
|
+
|
496
|
+
file = DR_GetFileName(FileName);
|
497
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
498
|
+
|
499
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("stat"), 2, file, fileinfo);
|
500
|
+
|
501
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
502
|
+
|
503
|
+
if (!RTEST(ret))
|
504
|
+
return -1;
|
505
|
+
|
506
|
+
Check_Type(ret, T_ARRAY);
|
507
|
+
|
508
|
+
if (RARRAY(ret)->len != 5) {
|
509
|
+
fprintf(stderr, "array size should be 5");
|
510
|
+
return -1;
|
511
|
+
}
|
512
|
+
|
513
|
+
HandleFileInformation->nFileSizeLow = NUM2ULONG(rb_ary_entry(ret,0));
|
514
|
+
HandleFileInformation->dwFileAttributes = NUM2ULONG(rb_ary_entry(ret,1));
|
515
|
+
|
516
|
+
DR_UnixTimeToFileTime(NUM2LONG(rb_ary_entry(ret,2)),
|
517
|
+
&HandleFileInformation->ftCreationTime);
|
518
|
+
DR_UnixTimeToFileTime(NUM2LONG(rb_ary_entry(ret,3)),
|
519
|
+
&HandleFileInformation->ftLastAccessTime);
|
520
|
+
DR_UnixTimeToFileTime(NUM2LONG(rb_ary_entry(ret,4)),
|
521
|
+
&HandleFileInformation->ftLastWriteTime);
|
522
|
+
|
523
|
+
return 0;
|
524
|
+
}
|
525
|
+
|
526
|
+
|
527
|
+
static int
|
528
|
+
DR_FindFiles(
|
529
|
+
LPCWSTR FileName,
|
530
|
+
PFillFindData FillFindData,
|
531
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
532
|
+
{
|
533
|
+
VALUE file, fileinfo;
|
534
|
+
VALUE ret;
|
535
|
+
int i;
|
536
|
+
|
537
|
+
DR_DebugPrint(L"FindFiles %ws\n", FileName);
|
538
|
+
|
539
|
+
/*
|
540
|
+
not implemented:
|
541
|
+
readdira(path, fileinfo)
|
542
|
+
[ [name, size, attr, ctime, atime, mtime], [], ]
|
543
|
+
*/
|
544
|
+
|
545
|
+
|
546
|
+
file = DR_GetFileName(FileName);
|
547
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
548
|
+
|
549
|
+
//rb_gc_disable();
|
550
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("readdir"), 2, file, fileinfo);
|
551
|
+
|
552
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
553
|
+
|
554
|
+
if (!RTEST(ret))
|
555
|
+
return -1;
|
556
|
+
|
557
|
+
Check_Type(ret, T_ARRAY);
|
558
|
+
|
559
|
+
for (i = 0; i<RARRAY(ret)->len; ++i) {
|
560
|
+
WCHAR filename[MAX_PATH];
|
561
|
+
WIN32_FIND_DATAW find;
|
562
|
+
BY_HANDLE_FILE_INFORMATION info;
|
563
|
+
size_t count;
|
564
|
+
|
565
|
+
VALUE entry = rb_ary_entry(ret,i);
|
566
|
+
|
567
|
+
StringValue(entry);
|
568
|
+
|
569
|
+
ZeroMemory(&find, sizeof(WIN32_FIND_DATAW));
|
570
|
+
ZeroMemory(&info, sizeof(BY_HANDLE_FILE_INFORMATION));
|
571
|
+
|
572
|
+
count = mbstowcs(find.cFileName, RSTRING(entry)->ptr, RSTRING(entry)->len);
|
573
|
+
|
574
|
+
find.dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
|
575
|
+
|
576
|
+
ZeroMemory(filename, sizeof(filename));
|
577
|
+
wcscat(filename, FileName);
|
578
|
+
wcscat(filename, find.cFileName);
|
579
|
+
|
580
|
+
if (DR_GetFileInformation(filename, &info, DokanFileInfo) == 0) {
|
581
|
+
|
582
|
+
find.dwFileAttributes = info.dwFileAttributes;
|
583
|
+
find.ftCreationTime = info.ftCreationTime;
|
584
|
+
find.ftLastAccessTime = info.ftLastAccessTime;
|
585
|
+
find.ftLastWriteTime = info.ftLastWriteTime;
|
586
|
+
find.nFileSizeLow = info.nFileSizeLow;
|
587
|
+
}
|
588
|
+
|
589
|
+
FillFindData(&find, DokanFileInfo);
|
590
|
+
}
|
591
|
+
//rb_gc_enable();
|
592
|
+
return 0;
|
593
|
+
}
|
594
|
+
|
595
|
+
|
596
|
+
static int
|
597
|
+
DR_SetFileAttributes(
|
598
|
+
LPCWSTR FileName,
|
599
|
+
DWORD FileAttributes,
|
600
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
601
|
+
{
|
602
|
+
VALUE file, fileinfo, attr;
|
603
|
+
VALUE ret;
|
604
|
+
|
605
|
+
DR_DebugPrint(L"SetFileAttributes %ws\n", FileName);
|
606
|
+
|
607
|
+
file = DR_GetFileName(FileName);
|
608
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
609
|
+
|
610
|
+
attr = ULONG2NUM(FileAttributes);
|
611
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("setattr"), 3, file, attr, fileinfo);
|
612
|
+
|
613
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
614
|
+
|
615
|
+
return RTEST(ret) ? 0 : -1;
|
616
|
+
}
|
617
|
+
|
618
|
+
static int
|
619
|
+
DR_FileTimeToUnixTime(
|
620
|
+
CONST FILETIME* Time)
|
621
|
+
{
|
622
|
+
LONGLONG ll = (LONGLONG)Time->dwLowDateTime + Time->dwHighDateTime << 32;
|
623
|
+
return (int)(( ll - 0x19DB1DED53E8000 ) / 10000000);
|
624
|
+
}
|
625
|
+
|
626
|
+
|
627
|
+
static int
|
628
|
+
DR_SetFileTime(
|
629
|
+
LPCWSTR FileName,
|
630
|
+
CONST FILETIME* CreationTime,
|
631
|
+
CONST FILETIME* LastAccessTime,
|
632
|
+
CONST FILETIME* LastWriteTime,
|
633
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
634
|
+
{
|
635
|
+
VALUE file, fileinfo;
|
636
|
+
VALUE ctime, atime, mtime;
|
637
|
+
VALUE ret;
|
638
|
+
|
639
|
+
DR_DebugPrint(L"SetFileTime %ws\n", FileName);
|
640
|
+
|
641
|
+
file = DR_GetFileName(FileName);
|
642
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
643
|
+
|
644
|
+
ctime = INT2NUM(DR_FileTimeToUnixTime(CreationTime));
|
645
|
+
atime = INT2NUM(DR_FileTimeToUnixTime(LastAccessTime));
|
646
|
+
mtime = INT2NUM(DR_FileTimeToUnixTime(LastWriteTime));
|
647
|
+
|
648
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("utime"), 5, file, ctime, atime, mtime, fileinfo);
|
649
|
+
|
650
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
651
|
+
|
652
|
+
return RTEST(ret) ? 0 : -1;
|
653
|
+
}
|
654
|
+
|
655
|
+
|
656
|
+
static int
|
657
|
+
DR_DeleteFile(
|
658
|
+
LPCWSTR FileName,
|
659
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
660
|
+
{
|
661
|
+
VALUE file, fileinfo;
|
662
|
+
VALUE ret;
|
663
|
+
|
664
|
+
DR_DebugPrint(L"DeleteFile %ws\n", FileName);
|
665
|
+
|
666
|
+
file = DR_GetFileName(FileName);
|
667
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
668
|
+
|
669
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("remove"), 2, file, fileinfo);
|
670
|
+
|
671
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
672
|
+
|
673
|
+
return RTEST(ret) ? 0 : -1;
|
674
|
+
}
|
675
|
+
|
676
|
+
|
677
|
+
static int
|
678
|
+
DR_DeleteDirectory(
|
679
|
+
LPCWSTR FileName,
|
680
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
681
|
+
{
|
682
|
+
VALUE file, fileinfo;
|
683
|
+
VALUE ret;
|
684
|
+
|
685
|
+
DR_DebugPrint(L"DeleteDirectory %ws\n", FileName);
|
686
|
+
|
687
|
+
file = DR_GetFileName(FileName);
|
688
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
689
|
+
|
690
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("rmdir"), 2, file, fileinfo);
|
691
|
+
|
692
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
693
|
+
|
694
|
+
return RTEST(ret) ? 0 : -1;
|
695
|
+
}
|
696
|
+
|
697
|
+
|
698
|
+
static int
|
699
|
+
DR_MoveFile(
|
700
|
+
LPCWSTR FileName,
|
701
|
+
LPCWSTR NewFileName,
|
702
|
+
BOOL ReplaceIfExisting,
|
703
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
704
|
+
{
|
705
|
+
VALUE file, newfile, fileinfo;
|
706
|
+
VALUE ret;
|
707
|
+
ULONG size;
|
708
|
+
|
709
|
+
DR_DebugPrint(L"MoveFile %ws => %ws\n", FileName, NewFileName);
|
710
|
+
|
711
|
+
file = DR_GetFileName(FileName);
|
712
|
+
newfile = DR_GetFileName(NewFileName);
|
713
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
714
|
+
|
715
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("rename"), 3, file, newfile, fileinfo);
|
716
|
+
|
717
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
718
|
+
|
719
|
+
return RTEST(ret) ? 0 : -1;
|
720
|
+
}
|
721
|
+
|
722
|
+
|
723
|
+
|
724
|
+
static int
|
725
|
+
DR_SetEndOfFile(
|
726
|
+
LPCWSTR FileName,
|
727
|
+
LONGLONG ByteOffset,
|
728
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
729
|
+
{
|
730
|
+
VALUE file, length, fileinfo;
|
731
|
+
VALUE ret;
|
732
|
+
|
733
|
+
DR_DebugPrint(L"SetEndOfFile %ws\n", FileName);
|
734
|
+
|
735
|
+
file = DR_GetFileName(FileName);
|
736
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
737
|
+
|
738
|
+
length = ULONG2NUM((ULONG)ByteOffset);
|
739
|
+
|
740
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("truncate"), 3, file, length, fileinfo);
|
741
|
+
|
742
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
743
|
+
|
744
|
+
return RTEST(ret) ? 0 : -1;
|
745
|
+
}
|
746
|
+
|
747
|
+
|
748
|
+
static int
|
749
|
+
DR_LockFile(
|
750
|
+
LPCWSTR FileName,
|
751
|
+
LONGLONG ByteOffset,
|
752
|
+
LONGLONG Length,
|
753
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
754
|
+
{
|
755
|
+
VALUE file, offset, length, fileinfo;
|
756
|
+
VALUE ret;
|
757
|
+
|
758
|
+
DR_DebugPrint(L"LockFile %ws\n", FileName);
|
759
|
+
|
760
|
+
file = DR_GetFileName(FileName);
|
761
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
762
|
+
|
763
|
+
offset = ULONG2NUM((ULONG)ByteOffset);
|
764
|
+
length = ULONG2NUM((ULONG)Length);
|
765
|
+
|
766
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("lock"), 4, file, offset, length, fileinfo);
|
767
|
+
|
768
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
769
|
+
|
770
|
+
return RTEST(ret) ? 0 : -1;
|
771
|
+
}
|
772
|
+
|
773
|
+
|
774
|
+
static int
|
775
|
+
DR_UnlockFile(
|
776
|
+
LPCWSTR FileName,
|
777
|
+
LONGLONG ByteOffset,
|
778
|
+
LONGLONG Length,
|
779
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
780
|
+
{
|
781
|
+
VALUE file, offset, length, fileinfo;
|
782
|
+
VALUE ret;
|
783
|
+
|
784
|
+
DR_DebugPrint(L"UnlockFile %ws\n", FileName);
|
785
|
+
|
786
|
+
file = DR_GetFileName(FileName);
|
787
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
788
|
+
|
789
|
+
offset = ULONG2NUM((ULONG)ByteOffset);
|
790
|
+
length = ULONG2NUM((ULONG)Length);
|
791
|
+
|
792
|
+
ret = rb_funcall(g_DokanRoot, rb_intern("unlock"), 4, file, offset, length, fileinfo);
|
793
|
+
|
794
|
+
DR_SetFileContext(DokanFileInfo, fileinfo);
|
795
|
+
|
796
|
+
return RTEST(ret) ? 0 : -1;
|
797
|
+
}
|
798
|
+
|
799
|
+
|
800
|
+
static int
|
801
|
+
DR_Unmount(
|
802
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
803
|
+
{
|
804
|
+
VALUE fileinfo;
|
805
|
+
|
806
|
+
DR_DebugPrint(L"Unmount\n");
|
807
|
+
|
808
|
+
fileinfo = DR_GetFileInfo(DokanFileInfo);
|
809
|
+
rb_funcall(g_DokanRoot, rb_intern("unmount"), 1, fileinfo);
|
810
|
+
|
811
|
+
return 0;
|
812
|
+
}
|
813
|
+
|
814
|
+
|
815
|
+
typedef struct _EVENT_ENTRY
|
816
|
+
{
|
817
|
+
ULONG Function;
|
818
|
+
PVOID Args;
|
819
|
+
HANDLE Event;
|
820
|
+
LIST_ENTRY ListEntry;
|
821
|
+
} EVENT_ENTRY, *PEVENT_ENTRY;
|
822
|
+
|
823
|
+
|
824
|
+
static VOID
|
825
|
+
DR_DispatchAndWait(
|
826
|
+
ULONG Function,
|
827
|
+
PVOID Args)
|
828
|
+
{
|
829
|
+
PEVENT_ENTRY entry = (PEVENT_ENTRY)malloc(sizeof(EVENT_ENTRY));
|
830
|
+
entry->Function = Function;
|
831
|
+
entry->Args = Args;
|
832
|
+
entry->Event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
833
|
+
|
834
|
+
WaitForSingleObject(g_DispatchMutex, INFINITE);
|
835
|
+
InsertTailList(&g_EventQueue, &entry->ListEntry);
|
836
|
+
SetEvent(g_DispatchEvent);
|
837
|
+
ReleaseMutex(g_DispatchMutex);
|
838
|
+
|
839
|
+
WaitForSingleObject(entry->Event, INFINITE);
|
840
|
+
|
841
|
+
CloseHandle(entry->Event);
|
842
|
+
free(entry);
|
843
|
+
}
|
844
|
+
|
845
|
+
|
846
|
+
|
847
|
+
|
848
|
+
typedef struct _CREATE_FILE
|
849
|
+
{
|
850
|
+
LPCWSTR FileName;
|
851
|
+
DWORD AccessMode;
|
852
|
+
DWORD ShareMode;
|
853
|
+
DWORD CreationDisposition;
|
854
|
+
DWORD FlagsAndAttributes;
|
855
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
856
|
+
int Return;
|
857
|
+
} CREATE_FILE, *PCREATE_FILE;
|
858
|
+
|
859
|
+
|
860
|
+
static int DOKAN_CALLBACK
|
861
|
+
DR_CreateFile0(
|
862
|
+
LPCWSTR FileName,
|
863
|
+
DWORD AccessMode,
|
864
|
+
DWORD ShareMode,
|
865
|
+
DWORD CreationDisposition,
|
866
|
+
DWORD FlagsAndAttributes,
|
867
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
868
|
+
{
|
869
|
+
PCREATE_FILE args = (PCREATE_FILE)malloc(sizeof(CREATE_FILE));
|
870
|
+
int ret;
|
871
|
+
|
872
|
+
//DR_DebugPrint(L"CreateFile0 %ws\n", FileName);
|
873
|
+
|
874
|
+
args->FileName = FileName;
|
875
|
+
args->AccessMode = AccessMode;
|
876
|
+
args->ShareMode = ShareMode;
|
877
|
+
args->CreationDisposition = CreationDisposition;
|
878
|
+
args->FlagsAndAttributes = FlagsAndAttributes;
|
879
|
+
args->DokanFileInfo = DokanFileInfo;
|
880
|
+
args->Return = -1;
|
881
|
+
|
882
|
+
DR_DispatchAndWait(CREATE_FILE_F, args);
|
883
|
+
ret = args->Return;
|
884
|
+
free(args);
|
885
|
+
|
886
|
+
return ret;
|
887
|
+
}
|
888
|
+
|
889
|
+
|
890
|
+
typedef struct _CREATE_DIRECTORY
|
891
|
+
{
|
892
|
+
LPCWSTR FileName;
|
893
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
894
|
+
int Return;
|
895
|
+
} CREATE_DIRECTORY, *PCREATE_DIRECTORY;
|
896
|
+
|
897
|
+
|
898
|
+
static int DOKAN_CALLBACK
|
899
|
+
DR_CreateDirectory0(
|
900
|
+
LPCWSTR FileName,
|
901
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
902
|
+
{
|
903
|
+
PCREATE_DIRECTORY args = (PCREATE_DIRECTORY)malloc(sizeof(CREATE_DIRECTORY));
|
904
|
+
int ret;
|
905
|
+
|
906
|
+
//DR_DebugPrint(L"CreateDirectory0 %ws\n", FileName);
|
907
|
+
|
908
|
+
args->FileName = FileName;
|
909
|
+
args->DokanFileInfo = DokanFileInfo;
|
910
|
+
args->Return = -1;
|
911
|
+
|
912
|
+
DR_DispatchAndWait(CREATE_DIRECTORY_F, args);
|
913
|
+
ret = args->Return;
|
914
|
+
free(args);
|
915
|
+
|
916
|
+
return ret;
|
917
|
+
}
|
918
|
+
|
919
|
+
|
920
|
+
typedef struct _OPEN_DIRECTORY
|
921
|
+
{
|
922
|
+
LPCWSTR FileName;
|
923
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
924
|
+
int Return;
|
925
|
+
} OPEN_DIRECTORY, *POPEN_DIRECTORY;
|
926
|
+
|
927
|
+
|
928
|
+
static int DOKAN_CALLBACK
|
929
|
+
DR_OpenDirectory0(
|
930
|
+
LPCWSTR FileName,
|
931
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
932
|
+
{
|
933
|
+
POPEN_DIRECTORY args = (POPEN_DIRECTORY)malloc(sizeof(OPEN_DIRECTORY));
|
934
|
+
int ret;
|
935
|
+
|
936
|
+
//DR_DebugPrint(L"OpenDirectory0 %ws\n", FileName);
|
937
|
+
|
938
|
+
args->FileName = FileName;
|
939
|
+
args->DokanFileInfo = DokanFileInfo;
|
940
|
+
args->Return = -1;
|
941
|
+
|
942
|
+
DR_DispatchAndWait(OPEN_DIRECTORY_F, args);
|
943
|
+
ret = args->Return;
|
944
|
+
free(args);
|
945
|
+
|
946
|
+
return ret;
|
947
|
+
}
|
948
|
+
|
949
|
+
|
950
|
+
typedef struct _CLOSE_FILE
|
951
|
+
{
|
952
|
+
LPCWSTR FileName;
|
953
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
954
|
+
int Return;
|
955
|
+
} CLOSE_FILE, *PCLOSE_FILE;
|
956
|
+
|
957
|
+
|
958
|
+
static int DOKAN_CALLBACK
|
959
|
+
DR_CloseFile0(
|
960
|
+
LPCWSTR FileName,
|
961
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
962
|
+
{
|
963
|
+
PCLOSE_FILE args = (PCLOSE_FILE)malloc(sizeof(CLOSE_FILE));
|
964
|
+
int ret;
|
965
|
+
|
966
|
+
//DR_DebugPrint(L"CloseFile0 %ws\n", FileName);
|
967
|
+
|
968
|
+
args->FileName = FileName;
|
969
|
+
args->DokanFileInfo = DokanFileInfo;
|
970
|
+
args->Return = -1;
|
971
|
+
|
972
|
+
DR_DispatchAndWait(CLOSE_FILE_F, args);
|
973
|
+
ret = args->Return;
|
974
|
+
free(args);
|
975
|
+
|
976
|
+
return ret;
|
977
|
+
}
|
978
|
+
|
979
|
+
|
980
|
+
typedef struct _CLEANUP
|
981
|
+
{
|
982
|
+
LPCWSTR FileName;
|
983
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
984
|
+
int Return;
|
985
|
+
} CLEANUP, *PCLEANUP;
|
986
|
+
|
987
|
+
|
988
|
+
static int DOKAN_CALLBACK
|
989
|
+
DR_Cleanup0(
|
990
|
+
LPCWSTR FileName,
|
991
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
992
|
+
{
|
993
|
+
PCLOSE_FILE args = (PCLOSE_FILE)malloc(sizeof(CLOSE_FILE));
|
994
|
+
int ret;
|
995
|
+
|
996
|
+
//DR_DebugPrint(L"Cleanup0 %ws\n", FileName);
|
997
|
+
|
998
|
+
args->FileName = FileName;
|
999
|
+
args->DokanFileInfo = DokanFileInfo;
|
1000
|
+
args->Return = -1;
|
1001
|
+
|
1002
|
+
DR_DispatchAndWait(CLEANUP_F, args);
|
1003
|
+
ret = args->Return;
|
1004
|
+
free(args);
|
1005
|
+
|
1006
|
+
return ret;
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
|
1010
|
+
typedef struct _READ_FILE
|
1011
|
+
{
|
1012
|
+
LPCWSTR FileName;
|
1013
|
+
LPVOID Buffer;
|
1014
|
+
DWORD BufferLength;
|
1015
|
+
LPDWORD ReadLength;
|
1016
|
+
LONGLONG Offset;
|
1017
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1018
|
+
int Return;
|
1019
|
+
} READ_FILE, *PREAD_FILE;
|
1020
|
+
|
1021
|
+
|
1022
|
+
static int DOKAN_CALLBACK
|
1023
|
+
DR_ReadFile0(
|
1024
|
+
LPCWSTR FileName,
|
1025
|
+
LPVOID Buffer,
|
1026
|
+
DWORD BufferLength,
|
1027
|
+
LPDWORD ReadLength,
|
1028
|
+
LONGLONG Offset,
|
1029
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1030
|
+
{
|
1031
|
+
PREAD_FILE args = (PREAD_FILE)malloc(sizeof(READ_FILE));
|
1032
|
+
int ret;
|
1033
|
+
|
1034
|
+
//DR_DebugPrint(L"ReadFile0 %ws\n", FileName);
|
1035
|
+
|
1036
|
+
args->FileName = FileName;
|
1037
|
+
args->Buffer = Buffer;
|
1038
|
+
args->BufferLength = BufferLength;
|
1039
|
+
args->ReadLength = ReadLength;
|
1040
|
+
args->Offset = Offset;
|
1041
|
+
args->DokanFileInfo = DokanFileInfo;
|
1042
|
+
args->Return = -1;
|
1043
|
+
|
1044
|
+
DR_DispatchAndWait(READ_FILE_F, args);
|
1045
|
+
ret = args->Return;
|
1046
|
+
free(args);
|
1047
|
+
|
1048
|
+
return ret;
|
1049
|
+
}
|
1050
|
+
|
1051
|
+
|
1052
|
+
typedef struct _WRITE_FILE
|
1053
|
+
{
|
1054
|
+
LPCWSTR FileName;
|
1055
|
+
LPCVOID Buffer;
|
1056
|
+
DWORD NumberOfBytesToWrite;
|
1057
|
+
LPDWORD NumberOfBytesWritten;
|
1058
|
+
LONGLONG Offset;
|
1059
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1060
|
+
int Return;
|
1061
|
+
} WRITE_FILE, *PWRITE_FILE;
|
1062
|
+
|
1063
|
+
static int DOKAN_CALLBACK
|
1064
|
+
DR_WriteFile0(
|
1065
|
+
LPCWSTR FileName,
|
1066
|
+
LPCVOID Buffer,
|
1067
|
+
DWORD NumberOfBytesToWrite,
|
1068
|
+
LPDWORD NumberOfBytesWritten,
|
1069
|
+
LONGLONG Offset,
|
1070
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1071
|
+
{
|
1072
|
+
PWRITE_FILE args = (PWRITE_FILE)malloc(sizeof(WRITE_FILE));
|
1073
|
+
int ret;
|
1074
|
+
|
1075
|
+
//DR_DebugPrint(L"WriteFile0 %ws\n", FileName);
|
1076
|
+
|
1077
|
+
args->FileName = FileName;
|
1078
|
+
args->Buffer = Buffer;
|
1079
|
+
args->NumberOfBytesToWrite = NumberOfBytesToWrite;
|
1080
|
+
args->NumberOfBytesWritten = NumberOfBytesWritten;
|
1081
|
+
args->Offset = Offset;
|
1082
|
+
args->DokanFileInfo = DokanFileInfo;
|
1083
|
+
args->Return = -1;
|
1084
|
+
|
1085
|
+
DR_DispatchAndWait(WRITE_FILE_F, args);
|
1086
|
+
ret = args->Return;
|
1087
|
+
free(args);
|
1088
|
+
|
1089
|
+
return ret;
|
1090
|
+
}
|
1091
|
+
|
1092
|
+
|
1093
|
+
typedef struct _GET_FILE_INFO
|
1094
|
+
{
|
1095
|
+
LPCWSTR FileName;
|
1096
|
+
LPBY_HANDLE_FILE_INFORMATION HandleFileInformation;
|
1097
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1098
|
+
int Return;
|
1099
|
+
} GET_FILE_INFO, *PGET_FILE_INFO;
|
1100
|
+
|
1101
|
+
|
1102
|
+
static int DOKAN_CALLBACK
|
1103
|
+
DR_GetFileInformation0(
|
1104
|
+
LPCWSTR FileName,
|
1105
|
+
LPBY_HANDLE_FILE_INFORMATION HandleFileInformation,
|
1106
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1107
|
+
{
|
1108
|
+
PGET_FILE_INFO args = (PGET_FILE_INFO)malloc(sizeof(GET_FILE_INFO));
|
1109
|
+
int ret;
|
1110
|
+
|
1111
|
+
//DR_DebugPrint(L"GetFileInfo0 %ws\n", FileName);
|
1112
|
+
|
1113
|
+
args->FileName = FileName;
|
1114
|
+
args->HandleFileInformation = HandleFileInformation;
|
1115
|
+
args->DokanFileInfo = DokanFileInfo;
|
1116
|
+
args->Return = -1;
|
1117
|
+
|
1118
|
+
DR_DispatchAndWait(GET_FILE_INFO_F, args);
|
1119
|
+
ret = args->Return;
|
1120
|
+
free(args);
|
1121
|
+
|
1122
|
+
return ret;
|
1123
|
+
}
|
1124
|
+
|
1125
|
+
|
1126
|
+
typedef struct _FIND_FILES
|
1127
|
+
{
|
1128
|
+
LPCWSTR FileName;
|
1129
|
+
PFillFindData FillFindData;
|
1130
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1131
|
+
int Return;
|
1132
|
+
} FIND_FILES, *PFIND_FILES;
|
1133
|
+
|
1134
|
+
|
1135
|
+
static int DOKAN_CALLBACK
|
1136
|
+
DR_FindFiles0(
|
1137
|
+
LPCWSTR FileName,
|
1138
|
+
PFillFindData FillFindData,
|
1139
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1140
|
+
{
|
1141
|
+
PFIND_FILES args = (PFIND_FILES)malloc(sizeof(FIND_FILES));
|
1142
|
+
int ret;
|
1143
|
+
|
1144
|
+
//DR_DebugPrint(L"FindFiles0 %ws\n", FileName);
|
1145
|
+
|
1146
|
+
args->FileName = FileName;
|
1147
|
+
args->FillFindData = FillFindData;
|
1148
|
+
args->DokanFileInfo = DokanFileInfo;
|
1149
|
+
args->Return = -1;
|
1150
|
+
|
1151
|
+
DR_DispatchAndWait(FIND_FILES_F, args);
|
1152
|
+
ret = args->Return;
|
1153
|
+
free(args);
|
1154
|
+
|
1155
|
+
return ret;
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
typedef struct _DELETE_FILE
|
1159
|
+
{
|
1160
|
+
LPCWSTR FileName;
|
1161
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1162
|
+
HANDLE Event;
|
1163
|
+
int Return;
|
1164
|
+
} DELETE_FILE, *PDELETE_FILE;
|
1165
|
+
|
1166
|
+
static int DOKAN_CALLBACK
|
1167
|
+
DR_DeleteFile0(
|
1168
|
+
LPCWSTR FileName,
|
1169
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1170
|
+
{
|
1171
|
+
PDELETE_FILE args = (PDELETE_FILE)malloc(sizeof(DELETE_FILE));
|
1172
|
+
int ret;
|
1173
|
+
|
1174
|
+
//DR_DebugPrint(L"DeleteFile0 %ws\n", FileName);
|
1175
|
+
|
1176
|
+
args->FileName = FileName;
|
1177
|
+
args->DokanFileInfo = DokanFileInfo;
|
1178
|
+
args->Return = -1;
|
1179
|
+
|
1180
|
+
DR_DispatchAndWait(DELETE_FILE_F, args);
|
1181
|
+
ret = args->Return;
|
1182
|
+
free(args);
|
1183
|
+
|
1184
|
+
return ret;
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
|
1188
|
+
typedef struct _DELETE_DIRECTORY
|
1189
|
+
{
|
1190
|
+
LPCWSTR FileName;
|
1191
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1192
|
+
HANDLE Event;
|
1193
|
+
int Return;
|
1194
|
+
} DELETE_DIRECTORY, *PDELETE_DIRECTORY;
|
1195
|
+
|
1196
|
+
|
1197
|
+
static int DOKAN_CALLBACK
|
1198
|
+
DR_DeleteDirectory0(
|
1199
|
+
LPCWSTR FileName,
|
1200
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1201
|
+
{
|
1202
|
+
PDELETE_DIRECTORY args = (PDELETE_DIRECTORY)malloc(sizeof(DELETE_DIRECTORY));
|
1203
|
+
int ret;
|
1204
|
+
|
1205
|
+
//DR_DebugPrint(L"DeleteDirectory0 %ws\n", FileName);
|
1206
|
+
|
1207
|
+
args->FileName = FileName;
|
1208
|
+
args->DokanFileInfo = DokanFileInfo;
|
1209
|
+
args->Return = -1;
|
1210
|
+
|
1211
|
+
DR_DispatchAndWait(DELETE_DIRECTORY_F, args);
|
1212
|
+
ret = args->Return;
|
1213
|
+
free(args);
|
1214
|
+
|
1215
|
+
return ret;
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
|
1219
|
+
typedef struct _MOVE_FILE
|
1220
|
+
{
|
1221
|
+
LPCWSTR FileName;
|
1222
|
+
LPCWSTR NewFileName;
|
1223
|
+
BOOL ReplaceIfExisting;
|
1224
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1225
|
+
HANDLE Event;
|
1226
|
+
int Return;
|
1227
|
+
} MOVE_FILE, *PMOVE_FILE;
|
1228
|
+
|
1229
|
+
|
1230
|
+
static int DOKAN_CALLBACK
|
1231
|
+
DR_MoveFile0(
|
1232
|
+
LPCWSTR FileName,
|
1233
|
+
LPCWSTR NewFileName,
|
1234
|
+
BOOL ReplaceIfExisting,
|
1235
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1236
|
+
{
|
1237
|
+
PMOVE_FILE args = (PMOVE_FILE)malloc(sizeof(MOVE_FILE));
|
1238
|
+
int ret;
|
1239
|
+
|
1240
|
+
//DR_DebugPrint(L"MoveFile0 %ws\n", FileName);
|
1241
|
+
|
1242
|
+
args->FileName = FileName;
|
1243
|
+
args->NewFileName = NewFileName;
|
1244
|
+
args->ReplaceIfExisting = ReplaceIfExisting;
|
1245
|
+
args->DokanFileInfo = DokanFileInfo;
|
1246
|
+
args->Return = -1;
|
1247
|
+
|
1248
|
+
DR_DispatchAndWait(MOVE_FILE_F, args);
|
1249
|
+
ret = args->Return;
|
1250
|
+
free(args);
|
1251
|
+
|
1252
|
+
return ret;
|
1253
|
+
}
|
1254
|
+
|
1255
|
+
|
1256
|
+
typedef struct _SET_FILE_ATTR
|
1257
|
+
{
|
1258
|
+
LPCWSTR FileName;
|
1259
|
+
DWORD FileAttributes;
|
1260
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1261
|
+
HANDLE Event;
|
1262
|
+
int Return;
|
1263
|
+
} SET_FILE_ATTR, *PSET_FILE_ATTR;
|
1264
|
+
|
1265
|
+
|
1266
|
+
static int DOKAN_CALLBACK
|
1267
|
+
DR_SetFileAttributes0(
|
1268
|
+
LPCWSTR FileName,
|
1269
|
+
DWORD FileAttributes,
|
1270
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1271
|
+
{
|
1272
|
+
PSET_FILE_ATTR args = (PSET_FILE_ATTR)malloc(sizeof(SET_FILE_ATTR));
|
1273
|
+
int ret;
|
1274
|
+
|
1275
|
+
//DR_DebugPrint(L"SetFileAttributes0 %ws\n", FileName);
|
1276
|
+
|
1277
|
+
args->FileName = FileName;
|
1278
|
+
args->FileAttributes = FileAttributes;
|
1279
|
+
args->DokanFileInfo = DokanFileInfo;
|
1280
|
+
args->Return = -1;
|
1281
|
+
|
1282
|
+
DR_DispatchAndWait(SET_FILE_ATTR_F, args);
|
1283
|
+
ret = args->Return;
|
1284
|
+
free(args);
|
1285
|
+
|
1286
|
+
return ret;
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
|
1290
|
+
typedef struct _SET_FILE_TIME
|
1291
|
+
{
|
1292
|
+
LPCWSTR FileName;
|
1293
|
+
CONST FILETIME* CreationTime;
|
1294
|
+
CONST FILETIME* LastAccessTime;
|
1295
|
+
CONST FILETIME* LastWriteTime;
|
1296
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1297
|
+
HANDLE Event;
|
1298
|
+
int Return;
|
1299
|
+
} SET_FILE_TIME, *PSET_FILE_TIME;
|
1300
|
+
|
1301
|
+
static int DOKAN_CALLBACK
|
1302
|
+
DR_SetFileTime0(
|
1303
|
+
LPCWSTR FileName,
|
1304
|
+
CONST FILETIME* CreationTime,
|
1305
|
+
CONST FILETIME* LastAccessTime,
|
1306
|
+
CONST FILETIME* LastWriteTime,
|
1307
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1308
|
+
{
|
1309
|
+
PSET_FILE_TIME args = (PSET_FILE_TIME)malloc(sizeof(SET_FILE_TIME));
|
1310
|
+
int ret;
|
1311
|
+
|
1312
|
+
//DR_DebugPrint(L"SetFileTime0 %ws\n", FileName);
|
1313
|
+
|
1314
|
+
args->FileName = FileName;
|
1315
|
+
args->CreationTime = CreationTime;
|
1316
|
+
args->LastAccessTime = LastAccessTime;
|
1317
|
+
args->LastWriteTime = LastWriteTime;
|
1318
|
+
args->Return = -1;
|
1319
|
+
|
1320
|
+
DR_DispatchAndWait(SET_FILE_TIME_F, args);
|
1321
|
+
ret = args->Return;
|
1322
|
+
free(args);
|
1323
|
+
|
1324
|
+
return ret;
|
1325
|
+
}
|
1326
|
+
|
1327
|
+
|
1328
|
+
typedef struct _SET_END_OF_FILE
|
1329
|
+
{
|
1330
|
+
LPCWSTR FileName;
|
1331
|
+
LONGLONG ByteOffset;
|
1332
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1333
|
+
int Return;
|
1334
|
+
} SET_END_OF_FILE, *PSET_END_OF_FILE;
|
1335
|
+
|
1336
|
+
static int DOKAN_CALLBACK
|
1337
|
+
DR_SetEndOfFile0(
|
1338
|
+
LPCWSTR FileName,
|
1339
|
+
LONGLONG ByteOffset,
|
1340
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1341
|
+
{
|
1342
|
+
PSET_END_OF_FILE args = (PSET_END_OF_FILE)malloc(sizeof(SET_END_OF_FILE));
|
1343
|
+
int ret;
|
1344
|
+
|
1345
|
+
//DR_DebugPrint(L"SetEndOfFile0 %ws\n", FileName);
|
1346
|
+
|
1347
|
+
args->FileName = FileName;
|
1348
|
+
args->ByteOffset = ByteOffset;
|
1349
|
+
args->DokanFileInfo = DokanFileInfo;
|
1350
|
+
args->Return = -1;
|
1351
|
+
|
1352
|
+
DR_DispatchAndWait(SET_END_OF_FILE_F, args);
|
1353
|
+
ret = args->Return;
|
1354
|
+
free(args);
|
1355
|
+
|
1356
|
+
return ret;
|
1357
|
+
}
|
1358
|
+
|
1359
|
+
|
1360
|
+
|
1361
|
+
typedef struct _LOCK_FILE
|
1362
|
+
{
|
1363
|
+
LPCWSTR FileName;
|
1364
|
+
LONGLONG ByteOffset;
|
1365
|
+
LONGLONG Length;
|
1366
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1367
|
+
int Return;
|
1368
|
+
} LOCK_FILE, *PLOCK_FILE;
|
1369
|
+
|
1370
|
+
static int DOKAN_CALLBACK
|
1371
|
+
DR_LockFile0(
|
1372
|
+
LPCWSTR FileName,
|
1373
|
+
LONGLONG ByteOffset,
|
1374
|
+
LONGLONG Length,
|
1375
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1376
|
+
{
|
1377
|
+
PLOCK_FILE args = (PLOCK_FILE)malloc(sizeof(LOCK_FILE));
|
1378
|
+
int ret;
|
1379
|
+
|
1380
|
+
//DR_DebugPrint(L"LockFile0 %ws\n", FileName);
|
1381
|
+
|
1382
|
+
args->FileName = FileName;
|
1383
|
+
args->ByteOffset = ByteOffset;
|
1384
|
+
args->Length = Length;
|
1385
|
+
args->DokanFileInfo = DokanFileInfo;
|
1386
|
+
args->Return = -1;
|
1387
|
+
|
1388
|
+
DR_DispatchAndWait(LOCK_FILE_F, args);
|
1389
|
+
ret = args->Return;
|
1390
|
+
free(args);
|
1391
|
+
|
1392
|
+
return ret;
|
1393
|
+
}
|
1394
|
+
|
1395
|
+
|
1396
|
+
|
1397
|
+
typedef struct _UNLOCK_FILE
|
1398
|
+
{
|
1399
|
+
LPCWSTR FileName;
|
1400
|
+
LONGLONG ByteOffset;
|
1401
|
+
LONGLONG Length;
|
1402
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1403
|
+
int Return;
|
1404
|
+
} UNLOCK_FILE, *PUNLOCK_FILE;
|
1405
|
+
|
1406
|
+
static int DOKAN_CALLBACK
|
1407
|
+
DR_UnlockFile0(
|
1408
|
+
LPCWSTR FileName,
|
1409
|
+
LONGLONG ByteOffset,
|
1410
|
+
LONGLONG Length,
|
1411
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1412
|
+
{
|
1413
|
+
PUNLOCK_FILE args = (PUNLOCK_FILE)malloc(sizeof(UNLOCK_FILE));
|
1414
|
+
int ret;
|
1415
|
+
|
1416
|
+
//DR_DebugPrint(L"UnlockFile0 %ws\n", FileName);
|
1417
|
+
|
1418
|
+
args->FileName = FileName;
|
1419
|
+
args->ByteOffset = ByteOffset;
|
1420
|
+
args->Length = Length;
|
1421
|
+
args->DokanFileInfo = DokanFileInfo;
|
1422
|
+
args->Return = -1;
|
1423
|
+
|
1424
|
+
DR_DispatchAndWait(UNLOCK_FILE_F, args);
|
1425
|
+
ret = args->Return;
|
1426
|
+
free(args);
|
1427
|
+
|
1428
|
+
return ret;
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
|
1432
|
+
|
1433
|
+
typedef struct _UNMOUNT
|
1434
|
+
{
|
1435
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1436
|
+
int Return;
|
1437
|
+
} UNMOUNT, *PUNMOUNT;
|
1438
|
+
|
1439
|
+
static int DOKAN_CALLBACK
|
1440
|
+
DR_Unmount0(
|
1441
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1442
|
+
{
|
1443
|
+
PUNMOUNT args = (PUNMOUNT)malloc(sizeof(UNMOUNT));
|
1444
|
+
int ret;
|
1445
|
+
|
1446
|
+
//DR_DebugPrint(L"Unmount0\n");
|
1447
|
+
|
1448
|
+
args->DokanFileInfo = DokanFileInfo;
|
1449
|
+
args->Return = -1;
|
1450
|
+
|
1451
|
+
DR_DispatchAndWait(UNMOUNT_F, args);
|
1452
|
+
ret = args->Return;
|
1453
|
+
free(args);
|
1454
|
+
|
1455
|
+
return ret;
|
1456
|
+
}
|
1457
|
+
|
1458
|
+
|
1459
|
+
typedef struct _FLUSH
|
1460
|
+
{
|
1461
|
+
LPCWSTR FileName;
|
1462
|
+
PDOKAN_FILE_INFO DokanFileInfo;
|
1463
|
+
int Return;
|
1464
|
+
} FLUSH, *PFLUSH;
|
1465
|
+
|
1466
|
+
static int DOKAN_CALLBACK
|
1467
|
+
DR_FlushFileBuffers0(
|
1468
|
+
LPCWSTR FileName,
|
1469
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1470
|
+
{
|
1471
|
+
PFLUSH args = (PFLUSH)malloc(sizeof(FLUSH));
|
1472
|
+
int ret;
|
1473
|
+
|
1474
|
+
args->FileName = FileName;
|
1475
|
+
args->DokanFileInfo = DokanFileInfo;
|
1476
|
+
args->Return = -1;
|
1477
|
+
|
1478
|
+
DR_DispatchAndWait(FLUSH_F, args);
|
1479
|
+
ret = args->Return;
|
1480
|
+
free(args);
|
1481
|
+
|
1482
|
+
return ret;
|
1483
|
+
}
|
1484
|
+
|
1485
|
+
|
1486
|
+
static DOKAN_OPERATIONS
|
1487
|
+
dokanOperations = {
|
1488
|
+
DR_CreateFile0,
|
1489
|
+
DR_OpenDirectory0,
|
1490
|
+
DR_CreateDirectory0,
|
1491
|
+
DR_Cleanup0,
|
1492
|
+
DR_CloseFile0,
|
1493
|
+
DR_ReadFile0,
|
1494
|
+
DR_WriteFile0,
|
1495
|
+
DR_FlushFileBuffers0,
|
1496
|
+
DR_GetFileInformation0,
|
1497
|
+
DR_FindFiles0,
|
1498
|
+
NULL, // FindFilesWithPattern
|
1499
|
+
DR_SetFileAttributes0,
|
1500
|
+
DR_SetFileTime0,
|
1501
|
+
DR_DeleteFile0,
|
1502
|
+
DR_DeleteDirectory0,
|
1503
|
+
DR_MoveFile0,
|
1504
|
+
DR_SetEndOfFile0,
|
1505
|
+
DR_LockFile0,
|
1506
|
+
DR_UnlockFile0,
|
1507
|
+
NULL, // GetDiskFreeSpace
|
1508
|
+
NULL, // GetVolumeInformation
|
1509
|
+
DR_Unmount0
|
1510
|
+
};
|
1511
|
+
|
1512
|
+
|
1513
|
+
static PEVENT_ENTRY CurrentEvent;
|
1514
|
+
|
1515
|
+
static VALUE
|
1516
|
+
DR_catch_exception(
|
1517
|
+
VALUE arg)
|
1518
|
+
{
|
1519
|
+
PEVENT_ENTRY entry = CurrentEvent;
|
1520
|
+
|
1521
|
+
switch (entry->Function) {
|
1522
|
+
case CREATE_FILE_F:
|
1523
|
+
{
|
1524
|
+
PCREATE_FILE args = (PCREATE_FILE)entry->Args;
|
1525
|
+
args->Return = DR_CreateFile(
|
1526
|
+
args->FileName,
|
1527
|
+
args->AccessMode,
|
1528
|
+
args->ShareMode,
|
1529
|
+
args->CreationDisposition,
|
1530
|
+
args->FlagsAndAttributes,
|
1531
|
+
args->DokanFileInfo);
|
1532
|
+
}
|
1533
|
+
break;
|
1534
|
+
|
1535
|
+
case OPEN_DIRECTORY_F:
|
1536
|
+
{
|
1537
|
+
POPEN_DIRECTORY args = (POPEN_DIRECTORY)entry->Args;
|
1538
|
+
args->Return = DR_OpenDirectory(
|
1539
|
+
args->FileName,
|
1540
|
+
args->DokanFileInfo);
|
1541
|
+
}
|
1542
|
+
break;
|
1543
|
+
|
1544
|
+
case CREATE_DIRECTORY_F:
|
1545
|
+
{
|
1546
|
+
PCREATE_DIRECTORY args = (PCREATE_DIRECTORY)entry->Args;
|
1547
|
+
args->Return = DR_CreateDirectory(
|
1548
|
+
args->FileName,
|
1549
|
+
args->DokanFileInfo);
|
1550
|
+
}
|
1551
|
+
break;
|
1552
|
+
|
1553
|
+
case CLOSE_FILE_F:
|
1554
|
+
{
|
1555
|
+
PCLOSE_FILE args = (PCLOSE_FILE)entry->Args;
|
1556
|
+
args->Return = DR_CloseFile(
|
1557
|
+
args->FileName,
|
1558
|
+
args->DokanFileInfo);
|
1559
|
+
}
|
1560
|
+
break;
|
1561
|
+
|
1562
|
+
case READ_FILE_F:
|
1563
|
+
{
|
1564
|
+
PREAD_FILE args = (PREAD_FILE)entry->Args;
|
1565
|
+
args->Return = DR_ReadFile(
|
1566
|
+
args->FileName,
|
1567
|
+
args->Buffer,
|
1568
|
+
args->BufferLength,
|
1569
|
+
args->ReadLength,
|
1570
|
+
args->Offset,
|
1571
|
+
args->DokanFileInfo);
|
1572
|
+
}
|
1573
|
+
break;
|
1574
|
+
|
1575
|
+
case WRITE_FILE_F:
|
1576
|
+
{
|
1577
|
+
PWRITE_FILE args = (PWRITE_FILE)entry->Args;
|
1578
|
+
args->Return = DR_WriteFile(
|
1579
|
+
args->FileName,
|
1580
|
+
args->Buffer,
|
1581
|
+
args->NumberOfBytesToWrite,
|
1582
|
+
args->NumberOfBytesWritten,
|
1583
|
+
args->Offset,
|
1584
|
+
args->DokanFileInfo);
|
1585
|
+
}
|
1586
|
+
break;
|
1587
|
+
|
1588
|
+
case GET_FILE_INFO_F:
|
1589
|
+
{
|
1590
|
+
PGET_FILE_INFO args = (PGET_FILE_INFO)entry->Args;
|
1591
|
+
args->Return = DR_GetFileInformation(
|
1592
|
+
args->FileName,
|
1593
|
+
args->HandleFileInformation,
|
1594
|
+
args->DokanFileInfo);
|
1595
|
+
}
|
1596
|
+
break;
|
1597
|
+
|
1598
|
+
case FIND_FILES_F:
|
1599
|
+
{
|
1600
|
+
PFIND_FILES args = (PFIND_FILES)entry->Args;
|
1601
|
+
args->Return = DR_FindFiles(
|
1602
|
+
args->FileName,
|
1603
|
+
args->FillFindData,
|
1604
|
+
args->DokanFileInfo);
|
1605
|
+
}
|
1606
|
+
break;
|
1607
|
+
|
1608
|
+
case SET_FILE_ATTR_F:
|
1609
|
+
{
|
1610
|
+
PSET_FILE_ATTR args = (PSET_FILE_ATTR)entry->Args;
|
1611
|
+
args->Return = DR_SetFileAttributes(
|
1612
|
+
args->FileName,
|
1613
|
+
args->FileAttributes,
|
1614
|
+
args->DokanFileInfo);
|
1615
|
+
}
|
1616
|
+
break;
|
1617
|
+
|
1618
|
+
case SET_FILE_TIME_F:
|
1619
|
+
{
|
1620
|
+
PSET_FILE_TIME args = (PSET_FILE_TIME)entry->Args;
|
1621
|
+
args->Return = DR_SetFileTime(
|
1622
|
+
args->FileName,
|
1623
|
+
args->CreationTime,
|
1624
|
+
args->LastAccessTime,
|
1625
|
+
args->LastWriteTime,
|
1626
|
+
args->DokanFileInfo);
|
1627
|
+
}
|
1628
|
+
break;
|
1629
|
+
|
1630
|
+
case DELETE_FILE_F:
|
1631
|
+
{
|
1632
|
+
PDELETE_FILE args = (PDELETE_FILE)entry->Args;
|
1633
|
+
args->Return = DR_DeleteFile(
|
1634
|
+
args->FileName,
|
1635
|
+
args->DokanFileInfo);
|
1636
|
+
}
|
1637
|
+
break;
|
1638
|
+
|
1639
|
+
case DELETE_DIRECTORY_F:
|
1640
|
+
{
|
1641
|
+
PDELETE_DIRECTORY args = (PDELETE_DIRECTORY)entry->Args;
|
1642
|
+
args->Return = DR_DeleteDirectory(
|
1643
|
+
args->FileName,
|
1644
|
+
args->DokanFileInfo);
|
1645
|
+
}
|
1646
|
+
break;
|
1647
|
+
|
1648
|
+
case MOVE_FILE_F:
|
1649
|
+
{
|
1650
|
+
PMOVE_FILE args = (PMOVE_FILE)entry->Args;
|
1651
|
+
args->Return = DR_MoveFile(
|
1652
|
+
args->FileName,
|
1653
|
+
args->NewFileName,
|
1654
|
+
args->ReplaceIfExisting,
|
1655
|
+
args->DokanFileInfo);
|
1656
|
+
}
|
1657
|
+
break;
|
1658
|
+
|
1659
|
+
case SET_END_OF_FILE_F:
|
1660
|
+
{
|
1661
|
+
PSET_END_OF_FILE args = (PSET_END_OF_FILE)entry->Args;
|
1662
|
+
args->Return = DR_SetEndOfFile(
|
1663
|
+
args->FileName,
|
1664
|
+
args->ByteOffset,
|
1665
|
+
args->DokanFileInfo);
|
1666
|
+
}
|
1667
|
+
break;
|
1668
|
+
|
1669
|
+
case LOCK_FILE_F:
|
1670
|
+
{
|
1671
|
+
PLOCK_FILE args = (PLOCK_FILE)entry->Args;
|
1672
|
+
args->Return = DR_LockFile(
|
1673
|
+
args->FileName,
|
1674
|
+
args->ByteOffset,
|
1675
|
+
args->Length,
|
1676
|
+
args->DokanFileInfo);
|
1677
|
+
}
|
1678
|
+
break;
|
1679
|
+
|
1680
|
+
case UNLOCK_FILE_F:
|
1681
|
+
{
|
1682
|
+
PUNLOCK_FILE args = (PUNLOCK_FILE)entry->Args;
|
1683
|
+
args->Return = DR_UnlockFile(
|
1684
|
+
args->FileName,
|
1685
|
+
args->ByteOffset,
|
1686
|
+
args->Length,
|
1687
|
+
args->DokanFileInfo);
|
1688
|
+
}
|
1689
|
+
break;
|
1690
|
+
|
1691
|
+
case UNMOUNT_F:
|
1692
|
+
{
|
1693
|
+
PUNMOUNT args = (PUNMOUNT)entry->Args;
|
1694
|
+
args->Return = DR_Unmount(
|
1695
|
+
args->DokanFileInfo);
|
1696
|
+
}
|
1697
|
+
break;
|
1698
|
+
|
1699
|
+
case CLEANUP_F:
|
1700
|
+
{
|
1701
|
+
PCLEANUP args = (PCLEANUP)entry->Args;
|
1702
|
+
args->Return = DR_Cleanup(
|
1703
|
+
args->FileName,
|
1704
|
+
args->DokanFileInfo);
|
1705
|
+
}
|
1706
|
+
break;
|
1707
|
+
|
1708
|
+
case FLUSH_F:
|
1709
|
+
{
|
1710
|
+
PFLUSH args = (PFLUSH)entry->Args;
|
1711
|
+
args->Return = DR_Flush(
|
1712
|
+
args->FileName,
|
1713
|
+
args->DokanFileInfo);
|
1714
|
+
}
|
1715
|
+
break;
|
1716
|
+
|
1717
|
+
default:
|
1718
|
+
fprintf(stderr, "unknown dispatch\n");
|
1719
|
+
break;
|
1720
|
+
}
|
1721
|
+
|
1722
|
+
SetEvent(entry->Event);
|
1723
|
+
return Qnil;
|
1724
|
+
}
|
1725
|
+
|
1726
|
+
static int DOKAN_CALLBACK
|
1727
|
+
DR_Unmount_dummy(
|
1728
|
+
PDOKAN_FILE_INFO DokanFileInfo)
|
1729
|
+
{
|
1730
|
+
//fprintf(stderr, "Unmount dummy\n");
|
1731
|
+
return 0;
|
1732
|
+
}
|
1733
|
+
|
1734
|
+
static VALUE
|
1735
|
+
DR_dokan_unmount(
|
1736
|
+
VALUE self)
|
1737
|
+
{
|
1738
|
+
wchar_t letter;
|
1739
|
+
|
1740
|
+
VALUE drive = rb_iv_get(self, "@drive");
|
1741
|
+
|
1742
|
+
StringValue(drive);
|
1743
|
+
|
1744
|
+
mbtowc(&letter, RSTRING(drive)->ptr, 1);
|
1745
|
+
|
1746
|
+
DokanUnmount(letter);
|
1747
|
+
|
1748
|
+
return Qtrue;
|
1749
|
+
}
|
1750
|
+
|
1751
|
+
|
1752
|
+
static VALUE
|
1753
|
+
DR_rescue(
|
1754
|
+
VALUE arg)
|
1755
|
+
{
|
1756
|
+
PEVENT_ENTRY entry = CurrentEvent;
|
1757
|
+
|
1758
|
+
SetEvent(entry->Event);
|
1759
|
+
|
1760
|
+
// do not dispatch 'unmount'
|
1761
|
+
dokanOperations.Unmount = DR_Unmount_dummy;
|
1762
|
+
DR_dokan_unmount(g_cDokan);
|
1763
|
+
|
1764
|
+
// save ruby exception
|
1765
|
+
// rethrow it after unmounting
|
1766
|
+
rb_gv_set("$dokan_exception", rb_gv_get("$!"));
|
1767
|
+
return Qtrue;
|
1768
|
+
}
|
1769
|
+
|
1770
|
+
|
1771
|
+
static VALUE
|
1772
|
+
DR_rescue_unmount(
|
1773
|
+
VALUE arg)
|
1774
|
+
{
|
1775
|
+
PEVENT_ENTRY entry = CurrentEvent;
|
1776
|
+
SetEvent(entry->Event);
|
1777
|
+
|
1778
|
+
// save ruby exceptiton
|
1779
|
+
rb_gv_set("$dokan_exception", rb_gv_get("$!"));
|
1780
|
+
return Qtrue;
|
1781
|
+
}
|
1782
|
+
|
1783
|
+
|
1784
|
+
static int
|
1785
|
+
DR_Dispatch()
|
1786
|
+
{
|
1787
|
+
while(TRUE) {
|
1788
|
+
WaitForSingleObject(g_DispatchEvent, INFINITE);
|
1789
|
+
WaitForSingleObject(g_DispatchMutex, INFINITE);
|
1790
|
+
|
1791
|
+
while(!IsListEmpty(&g_EventQueue)) {
|
1792
|
+
PLIST_ENTRY listEntry = RemoveHeadList(&g_EventQueue);
|
1793
|
+
PEVENT_ENTRY entry = CONTAINING_RECORD(listEntry, EVENT_ENTRY, ListEntry);
|
1794
|
+
|
1795
|
+
CurrentEvent = entry;
|
1796
|
+
|
1797
|
+
if (entry->Function == UNMOUNT_F) {
|
1798
|
+
// when exception raised, DR_rescue is called
|
1799
|
+
// and DR_rescue returns Qtrue
|
1800
|
+
if (Qtrue == rb_rescue(DR_catch_exception, Qnil, DR_rescue_unmount, Qnil)) {
|
1801
|
+
//fprintf(stderr, "catch exception: unmount\n");
|
1802
|
+
ReleaseMutex(g_DispatchMutex);
|
1803
|
+
return -1;
|
1804
|
+
}
|
1805
|
+
ReleaseMutex(g_DispatchMutex);
|
1806
|
+
return 0;
|
1807
|
+
|
1808
|
+
} else {
|
1809
|
+
// when exception raised, DR_rescue is called and it returns Qtrue
|
1810
|
+
if (Qtrue == rb_rescue(DR_catch_exception, Qnil, DR_rescue, Qnil)) {
|
1811
|
+
//fprintf(stderr, "catch exception: method %u\n", entry->Function);
|
1812
|
+
ReleaseMutex(g_DispatchMutex);
|
1813
|
+
return -1;
|
1814
|
+
}
|
1815
|
+
}
|
1816
|
+
}
|
1817
|
+
ResetEvent(g_DispatchEvent);
|
1818
|
+
ReleaseMutex(g_DispatchMutex);
|
1819
|
+
}
|
1820
|
+
}
|
1821
|
+
|
1822
|
+
|
1823
|
+
static VALUE
|
1824
|
+
DR_dokan_set_root(
|
1825
|
+
VALUE self,
|
1826
|
+
VALUE obj)
|
1827
|
+
{
|
1828
|
+
g_DokanRoot = obj;
|
1829
|
+
|
1830
|
+
rb_iv_set(self, "@root", obj);
|
1831
|
+
return Qtrue;
|
1832
|
+
}
|
1833
|
+
|
1834
|
+
|
1835
|
+
static VALUE
|
1836
|
+
DR_dokan_mount_under(
|
1837
|
+
VALUE self,
|
1838
|
+
VALUE DriveLetter)
|
1839
|
+
{
|
1840
|
+
StringValue(DriveLetter);
|
1841
|
+
|
1842
|
+
rb_iv_set(self, "@drive", DriveLetter);
|
1843
|
+
|
1844
|
+
return self;
|
1845
|
+
}
|
1846
|
+
|
1847
|
+
|
1848
|
+
|
1849
|
+
static DWORD __stdcall
|
1850
|
+
DR_Main(
|
1851
|
+
PVOID Param)
|
1852
|
+
{
|
1853
|
+
DokanMain((PDOKAN_OPTIONS)Param, &dokanOperations);
|
1854
|
+
return 0;
|
1855
|
+
}
|
1856
|
+
|
1857
|
+
|
1858
|
+
|
1859
|
+
static VALUE
|
1860
|
+
DR_dokan_run(
|
1861
|
+
VALUE self)
|
1862
|
+
{
|
1863
|
+
wchar_t letter;
|
1864
|
+
HANDLE handle;
|
1865
|
+
ULONG threadId;
|
1866
|
+
int status;
|
1867
|
+
PDOKAN_OPTIONS dokanOptions;
|
1868
|
+
|
1869
|
+
VALUE drive = rb_iv_get(self, "@drive");
|
1870
|
+
|
1871
|
+
StringValue(drive);
|
1872
|
+
|
1873
|
+
mbtowc(&letter, RSTRING(drive)->ptr, 1);
|
1874
|
+
|
1875
|
+
if ( !(L'e' <= letter && letter <= L'z')
|
1876
|
+
&& !('E' <= letter && letter <= L'Z') ) {
|
1877
|
+
fprintf(stderr, "drive letter error");
|
1878
|
+
return Qfalse;
|
1879
|
+
}
|
1880
|
+
|
1881
|
+
dokanOptions = (PDOKAN_OPTIONS)malloc(sizeof(DOKAN_OPTIONS));
|
1882
|
+
ZeroMemory(dokanOptions, sizeof(DOKAN_OPTIONS));
|
1883
|
+
|
1884
|
+
dokanOptions->DriveLetter = letter;
|
1885
|
+
dokanOptions->ThreadCount = 0; // default
|
1886
|
+
dokanOptions->DebugMode = 0; // debug mode off
|
1887
|
+
|
1888
|
+
rb_iv_set(self, "@@mounted", Qtrue);
|
1889
|
+
|
1890
|
+
handle = (HANDLE)_beginthreadex(
|
1891
|
+
NULL,
|
1892
|
+
0,
|
1893
|
+
DR_Main,
|
1894
|
+
(PVOID)dokanOptions,
|
1895
|
+
0,
|
1896
|
+
&threadId);
|
1897
|
+
|
1898
|
+
status = DR_Dispatch();
|
1899
|
+
|
1900
|
+
Sleep(1000);
|
1901
|
+
//WaitForSingleObject(handle, INFINITE);
|
1902
|
+
|
1903
|
+
if (status < 0) {
|
1904
|
+
//fprintf(stderr, "raise exception\n");
|
1905
|
+
//rb_gv_set("$!", rb_gv_get("$dokan_exception"));
|
1906
|
+
rb_exc_raise(rb_gv_get("$dokan_exception"));
|
1907
|
+
}
|
1908
|
+
|
1909
|
+
free(dokanOptions);
|
1910
|
+
|
1911
|
+
return Qtrue;
|
1912
|
+
}
|
1913
|
+
|
1914
|
+
|
1915
|
+
static VALUE
|
1916
|
+
DR_dokan_mount(
|
1917
|
+
VALUE self,
|
1918
|
+
VALUE DriveLetter,
|
1919
|
+
VALUE Root)
|
1920
|
+
{
|
1921
|
+
StringValue(DriveLetter);
|
1922
|
+
|
1923
|
+
rb_iv_set(self, "@drive", DriveLetter);
|
1924
|
+
rb_iv_set(self, "@root", Root);
|
1925
|
+
|
1926
|
+
g_DokanRoot = Root;
|
1927
|
+
|
1928
|
+
return DR_dokan_run(self);
|
1929
|
+
}
|
1930
|
+
|
1931
|
+
static VALUE
|
1932
|
+
DR_dokan_set_debug(
|
1933
|
+
VALUE self,
|
1934
|
+
VALUE isDebug)
|
1935
|
+
{
|
1936
|
+
if(RTEST(isDebug))
|
1937
|
+
g_Debug = TRUE;
|
1938
|
+
else
|
1939
|
+
g_Debug = FALSE;
|
1940
|
+
|
1941
|
+
return Qnil;
|
1942
|
+
}
|
1943
|
+
|
1944
|
+
#define DR_define_const(klass, val) rb_define_const(klass, #val, INT2FIX(val))
|
1945
|
+
|
1946
|
+
void
|
1947
|
+
Init_dokan_lib()
|
1948
|
+
{
|
1949
|
+
InitializeListHead(&g_EventQueue);
|
1950
|
+
g_DispatchEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
1951
|
+
g_DispatchMutex = CreateMutex(NULL, FALSE, NULL);
|
1952
|
+
|
1953
|
+
setlocale(LC_ALL, "");
|
1954
|
+
|
1955
|
+
g_cDokan = rb_define_module("Dokan");
|
1956
|
+
//rb_define_singleton_method(g_cDokan, "mount_under", DR_dokan_mount_under, 1);
|
1957
|
+
rb_define_singleton_method(g_cDokan, "mount", DR_dokan_mount, 2);
|
1958
|
+
//rb_define_singleton_method(g_cDokan, "run", DR_dokan_run, 0);
|
1959
|
+
//rb_define_singleton_method(g_cDokan, "set_root", DR_dokan_set_root, 1);
|
1960
|
+
//rb_define_singleton_method(g_cDokan, "root=", DR_dokan_set_root, 1);
|
1961
|
+
rb_define_singleton_method(g_cDokan, "unmount", DR_dokan_unmount, 0);
|
1962
|
+
|
1963
|
+
rb_define_singleton_method(g_cDokan, "set_debug", DR_dokan_set_debug, 1);
|
1964
|
+
rb_define_singleton_method(g_cDokan, "debug=", DR_dokan_set_debug, 1);
|
1965
|
+
|
1966
|
+
rb_define_const(g_cDokan, "READONLY", INT2FIX(FILE_ATTRIBUTE_READONLY));
|
1967
|
+
rb_define_const(g_cDokan, "HIDDEN", INT2FIX(FILE_ATTRIBUTE_HIDDEN));
|
1968
|
+
rb_define_const(g_cDokan, "SYSTEM", INT2FIX(FILE_ATTRIBUTE_SYSTEM));
|
1969
|
+
rb_define_const(g_cDokan, "DIRECTORY", INT2FIX(FILE_ATTRIBUTE_DIRECTORY));
|
1970
|
+
rb_define_const(g_cDokan, "ARCHIVE", INT2FIX(FILE_ATTRIBUTE_ARCHIVE));
|
1971
|
+
//DR_define_const(g_cDokan, FILE_ATTRIBUTE_DEVICE);
|
1972
|
+
rb_define_const(g_cDokan, "NORMAL", INT2FIX(FILE_ATTRIBUTE_NORMAL));
|
1973
|
+
|
1974
|
+
rb_define_const(g_cDokan, "TEMPORARY", INT2FIX(FILE_ATTRIBUTE_TEMPORARY));
|
1975
|
+
rb_define_const(g_cDokan, "SPARSE_FILE", INT2FIX(FILE_ATTRIBUTE_SPARSE_FILE));
|
1976
|
+
rb_define_const(g_cDokan, "REPARSE_POINT", INT2FIX(FILE_ATTRIBUTE_REPARSE_POINT));
|
1977
|
+
rb_define_const(g_cDokan, "COMPRESSED", INT2FIX(FILE_ATTRIBUTE_COMPRESSED));
|
1978
|
+
|
1979
|
+
rb_define_const(g_cDokan, "OFFLINE", INT2FIX(FILE_ATTRIBUTE_OFFLINE));
|
1980
|
+
rb_define_const(g_cDokan, "NOT_CONTENT_INDEXED", INT2FIX(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED));
|
1981
|
+
rb_define_const(g_cDokan, "ENCRYPTED", INT2FIX(FILE_ATTRIBUTE_ENCRYPTED));
|
1982
|
+
|
1983
|
+
DR_DefineFileInfoClass();
|
1984
|
+
|
1985
|
+
rb_gv_set("$dokan_context", rb_ary_new());
|
1986
|
+
}
|
1987
|
+
|