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 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
+