dokan-ruby 0.0.1-mswin32

Sign up to get free protection for your applications and to get access to all the features.
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.
@@ -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.
@@ -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
@@ -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
+