forked from keybase/kbfs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bridge.c
412 lines (357 loc) · 16.3 KB
/
bridge.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
#include "bridge.h"
static const WCHAR dokansystem32[] = L"C:\\WINDOWS\\SYSTEM32\\DOKAN" DOKAN_MAJOR_API_VERSION L".DLL";
static const WCHAR dokansyswow64[] = L"C:\\WINDOWS\\SYSWOW64\\DOKAN" DOKAN_MAJOR_API_VERSION L".DLL";
static const WCHAR dokan1dll[] = L"DOKAN" DOKAN_MAJOR_API_VERSION L".DLL";
static BOOL __stdcall (*kbfsLibdokanPtr_RemoveMountPoint)(LPCWSTR MountPoint);
static HANDLE __stdcall (*kbfsLibdokanPtr_OpenRequestorToken)(PDOKAN_FILE_INFO DokanFileInfo);
static int __stdcall (*kbfsLibdokanPtr_Main)(PDOKAN_OPTIONS DokanOptions, PDOKAN_OPERATIONS DokanOperations);
DWORD kbfsLibdokanLoadLibrary(LPCWSTR location) {
int i;
BOOL defaultPath = FALSE;
// 0x800 is LOAD_LIBRARY_SEARCH_SYSTEM32 but that is not defined on build machines.
DWORD flags = 0x800;
if(!location) {
location = dokan1dll;
defaultPath = TRUE;
} else {
for(i=0; location[i]; i++)
if(location[i]== L'/' || location[i]==L'\\') {
flags = 0;
break;
}
}
HMODULE mod = LoadLibraryExW(location, NULL, flags);
if(mod == NULL) {
if(defaultPath && GetLastError()==ERROR_INVALID_PARAMETER) {
// User has not installed KB2533623 which is a security update
// from 2011. Without this Windows security update loading libraries
// is unsafe on Windows.
// Try SysWOW64 on 32 bit builds.
if(sizeof(void*)==4)
mod = LoadLibrary(dokansyswow64);
if(mod == NULL)
mod = LoadLibrary(dokansystem32);
if(mod == NULL)
mod = LoadLibrary(dokan1dll);
if(mod == NULL)
return GetLastError();
} else
return GetLastError();
}
kbfsLibdokanPtr_RemoveMountPoint = (void*)GetProcAddress(mod, "DokanRemoveMountPoint");
if(kbfsLibdokanPtr_RemoveMountPoint == NULL)
return GetLastError();
kbfsLibdokanPtr_OpenRequestorToken = (void*)GetProcAddress(mod, "DokanOpenRequestorToken");
if(kbfsLibdokanPtr_OpenRequestorToken == NULL)
return GetLastError();
kbfsLibdokanPtr_Main = (void*)GetProcAddress(mod, "DokanMain");
if(kbfsLibdokanPtr_Main == NULL)
return GetLastError();
return 0;
}
extern NTSTATUS kbfsLibdokanCreateFile(LPCWSTR FileName,
PDOKAN_IO_SECURITY_CONTEXT psec,
ACCESS_MASK DesiredAccess,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PDOKAN_FILE_INFO pfi);
extern DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_CreateFile(LPCWSTR FileName,
PDOKAN_IO_SECURITY_CONTEXT psec,
ACCESS_MASK DesiredAccess,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PDOKAN_FILE_INFO pfi) {
return kbfsLibdokanCreateFile(FileName,psec,DesiredAccess,FileAttributes,ShareAccess,CreateDisposition,CreateOptions,pfi);
}
extern void kbfsLibdokanCleanup(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK void kbfsLibdokanC_Cleanup(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo) {
kbfsLibdokanCleanup(FileName,FileInfo);
}
extern void kbfsLibdokanCloseFile(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK void kbfsLibdokanC_CloseFile(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo) {
kbfsLibdokanCloseFile(FileName,FileInfo);
}
extern NTSTATUS kbfsLibdokanReadFile(LPCWSTR FileName,
LPVOID Buffer,
DWORD NumberOfBytesToRead,
LPDWORD NumberOfBytesRead,
LONGLONG Offset,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_ReadFile(LPCWSTR FileName,
LPVOID Buffer,
DWORD NumberOfBytesToRead,
LPDWORD NumberOfBytesRead,
LONGLONG Offset,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanReadFile(FileName, Buffer, NumberOfBytesToRead, NumberOfBytesRead, Offset, FileInfo);
}
extern NTSTATUS kbfsLibdokanWriteFile(LPCWSTR FileName,
LPCVOID Buffer,
DWORD NumberOfBytesToWrite,
LPDWORD NumberOfBytesWritten,
LONGLONG Offset,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_WriteFile(LPCWSTR FileName,
LPCVOID Buffer,
DWORD NumberOfBytesToWrite,
LPDWORD NumberOfBytesWritten,
LONGLONG Offset,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanWriteFile(FileName, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, Offset, FileInfo);
}
extern NTSTATUS kbfsLibdokanFlushFileBuffers(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_FlushFileBuffers(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanFlushFileBuffers(FileName, FileInfo);
}
extern NTSTATUS kbfsLibdokanGetFileInformation(LPCWSTR FileName,
LPBY_HANDLE_FILE_INFORMATION Buffer,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_GetFileInformation(LPCWSTR FileName,
LPBY_HANDLE_FILE_INFORMATION Buffer,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanGetFileInformation(FileName, Buffer, FileInfo);
}
extern NTSTATUS kbfsLibdokanFindFiles(LPCWSTR PathName,
PFillFindData FindData, // call this function with PWIN32_FIND_DATAW
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_FindFiles(LPCWSTR PathName,
PFillFindData FindData, // call this function with PWIN32_FIND_DATAW
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanFindFiles(PathName, FindData, FileInfo);
}
extern NTSTATUS kbfsLibdokanFindFilesWithPattern(LPCWSTR PathName,
LPCWSTR SearchPattern,
PFillFindData FindData, // call this function with PWIN32_FIND_DATAW
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_FindFilesWithPattern(LPCWSTR PathName,
LPCWSTR SearchPattern,
PFillFindData FindData, // call this function with PWIN32_FIND_DATAW
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanFindFilesWithPattern(PathName, SearchPattern, FindData, FileInfo);
}
extern NTSTATUS kbfsLibdokanSetFileAttributes(LPCWSTR FileName,
DWORD FileAttributes,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_SetFileAttributes(LPCWSTR FileName,
DWORD FileAttributes,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanSetFileAttributes(FileName, FileAttributes, FileInfo);
}
extern NTSTATUS kbfsLibdokanSetFileTime(LPCWSTR FileName,
CONST FILETIME* CreationTime,
CONST FILETIME* LastAccessTime,
CONST FILETIME* LastWriteTime,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_SetFileTime(LPCWSTR FileName,
CONST FILETIME* CreationTime,
CONST FILETIME* LastAccessTime,
CONST FILETIME* LastWriteTime,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanSetFileTime(FileName, CreationTime, LastAccessTime, LastWriteTime, FileInfo);
}
extern NTSTATUS kbfsLibdokanDeleteFile(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_DeleteFile(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanDeleteFile(FileName, FileInfo);
}
extern NTSTATUS kbfsLibdokanDeleteDirectory(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_DeleteDirectory(LPCWSTR FileName, PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanDeleteDirectory(FileName, FileInfo);
}
extern NTSTATUS kbfsLibdokanMoveFile(LPCWSTR ExistingFileName,
LPCWSTR NewFileName,
BOOL ReplaceExisiting,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_MoveFile(LPCWSTR ExistingFileName,
LPCWSTR NewFileName,
BOOL ReplaceExisiting,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanMoveFile(ExistingFileName, NewFileName, ReplaceExisiting, FileInfo);
}
extern NTSTATUS kbfsLibdokanSetEndOfFile(LPCWSTR FileName,
LONGLONG Length,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_SetEndOfFile(LPCWSTR FileName,
LONGLONG Length,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanSetEndOfFile(FileName, Length, FileInfo);
}
extern NTSTATUS kbfsLibdokanSetAllocationSize(LPCWSTR FileName,
LONGLONG Length,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_SetAllocationSize(LPCWSTR FileName,
LONGLONG Length,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanSetAllocationSize(FileName, Length, FileInfo);
}
extern NTSTATUS kbfsLibdokanLockFile(LPCWSTR FileName,
LONGLONG ByteOffset,
LONGLONG Length,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_LockFile(LPCWSTR FileName,
LONGLONG ByteOffset,
LONGLONG Length,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanLockFile(FileName, ByteOffset, Length, FileInfo);
}
extern NTSTATUS kbfsLibdokanUnlockFile(LPCWSTR FileName,
LONGLONG ByteOffset,
LONGLONG Length,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_UnlockFile(LPCWSTR FileName,
LONGLONG ByteOffset,
LONGLONG Length,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanUnlockFile(FileName, ByteOffset, Length, FileInfo);
}
// see Win32 API GetDiskFreeSpaceEx
extern NTSTATUS kbfsLibdokanGetDiskFreeSpace(ULONGLONG* FreeBytesAvailable,
ULONGLONG* TotalNumberOfBytes,
ULONGLONG* TotalNumberOfFreeBytes,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_GetDiskFreeSpace(PULONGLONG FreeBytesAvailable,
PULONGLONG TotalNumberOfBytes,
PULONGLONG TotalNumberOfFreeBytes,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanGetDiskFreeSpace((ULONGLONG*)FreeBytesAvailable, (ULONGLONG*)TotalNumberOfBytes, (ULONGLONG*)TotalNumberOfFreeBytes, FileInfo);
}
// see Win32 API GetVolumeInformation
extern NTSTATUS kbfsLibdokanGetVolumeInformation(LPWSTR VolumeNameBuffer,
DWORD VolumeNameSize, // in num of chars
LPDWORD VolumeSerialNumber,
LPDWORD MaximumComponentLength, // in num of chars
LPDWORD FileSystemFlags,
LPWSTR FileSystemNameBuffer,
DWORD FileSystemNameSize, // in num of chars
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_GetVolumeInformation(LPWSTR VolumeNameBuffer,
DWORD VolumeNameSize, // in num of chars
LPDWORD VolumeSerialNumber,
LPDWORD MaximumComponentLength, // in num of chars
LPDWORD FileSystemFlags,
LPWSTR FileSystemNameBuffer,
DWORD FileSystemNameSize, // in num of chars
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanGetVolumeInformation(VolumeNameBuffer, VolumeNameSize, VolumeSerialNumber, MaximumComponentLength, FileSystemFlags, FileSystemNameBuffer, FileSystemNameSize, FileInfo);
}
extern NTSTATUS kbfsLibdokanMounted(PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_Mounted(PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanMounted(FileInfo);
}
extern NTSTATUS kbfsLibdokanGetFileSecurity(LPCWSTR FileName,
//A pointer to SECURITY_INFORMATION value being requested
PSECURITY_INFORMATION input,
// A pointer to SECURITY_DESCRIPTOR buffer to be filled
PSECURITY_DESCRIPTOR output,
ULONG outlen,// length of Security descriptor buffer
PULONG LengthNeeded,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_GetFileSecurity(LPCWSTR FileName,
//A pointer to SECURITY_INFORMATION value being requested
PSECURITY_INFORMATION input,
// A pointer to SECURITY_DESCRIPTOR buffer to be filled
PSECURITY_DESCRIPTOR output,
ULONG outlen,// length of Security descriptor buffer
PULONG LengthNeeded,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanGetFileSecurity(FileName, input, output, outlen, LengthNeeded, FileInfo);
}
extern NTSTATUS kbfsLibdokanSetFileSecurity(LPCWSTR FileName,
PSECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor,
ULONG SecurityDescriptorLength,
PDOKAN_FILE_INFO FileInfo);
static DOKAN_CALLBACK NTSTATUS kbfsLibdokanC_SetFileSecurity(LPCWSTR FileName,
PSECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor,
ULONG SecurityDescriptorLength,
PDOKAN_FILE_INFO FileInfo) {
return kbfsLibdokanSetFileSecurity(FileName, SecurityInformation, SecurityDescriptor, SecurityDescriptorLength, FileInfo);
}
/*
extern NTSTATUS kbfsLibdokanFindStreams(LPCWSTR FileName,
// call this function with PWIN32_FIND_STREAM_DATA
PFillFindStreamData FindStreamData,
PDOKAN_FILE_INFO FileInfo);
*/
struct kbfsLibdokanCtx* kbfsLibdokanAllocCtx(ULONG64 slot) {
struct kbfsLibdokanCtx *ctx = malloc(sizeof(struct kbfsLibdokanCtx));
if(!ctx)
return ctx;
memset(ctx, 0, sizeof(struct kbfsLibdokanCtx));
ctx->dokan_options.Version = DOKAN_VERSION;
// Dokan timeout 10 minutes... Disables - was related to dokan crashes!
// ctx->dokan_options.Timeout = 600 * 1000;
ctx->dokan_options.GlobalContext = slot;
ctx->dokan_operations.ZwCreateFile = kbfsLibdokanC_CreateFile;
ctx->dokan_operations.Cleanup = kbfsLibdokanC_Cleanup;
ctx->dokan_operations.CloseFile = kbfsLibdokanC_CloseFile;
ctx->dokan_operations.ReadFile = kbfsLibdokanC_ReadFile;
ctx->dokan_operations.WriteFile = kbfsLibdokanC_WriteFile;
ctx->dokan_operations.FlushFileBuffers = kbfsLibdokanC_FlushFileBuffers;
ctx->dokan_operations.GetFileInformation = kbfsLibdokanC_GetFileInformation;
ctx->dokan_operations.FindFiles = kbfsLibdokanC_FindFiles;
ctx->dokan_operations.SetFileAttributes = kbfsLibdokanC_SetFileAttributes;
ctx->dokan_operations.SetFileTime = kbfsLibdokanC_SetFileTime;
ctx->dokan_operations.DeleteFile = kbfsLibdokanC_DeleteFile;
ctx->dokan_operations.DeleteDirectory = kbfsLibdokanC_DeleteDirectory;
ctx->dokan_operations.MoveFile = kbfsLibdokanC_MoveFile;
ctx->dokan_operations.SetEndOfFile = kbfsLibdokanC_SetEndOfFile;
ctx->dokan_operations.SetAllocationSize = kbfsLibdokanC_SetAllocationSize;
ctx->dokan_operations.LockFile = kbfsLibdokanC_LockFile;
ctx->dokan_operations.UnlockFile = kbfsLibdokanC_UnlockFile;
ctx->dokan_operations.GetDiskFreeSpace = kbfsLibdokanC_GetDiskFreeSpace;
ctx->dokan_operations.GetVolumeInformation = kbfsLibdokanC_GetVolumeInformation;
ctx->dokan_operations.Mounted = kbfsLibdokanC_Mounted;
ctx->dokan_operations.GetFileSecurity = kbfsLibdokanC_GetFileSecurity;
ctx->dokan_operations.SetFileSecurity = kbfsLibdokanC_SetFileSecurity;
// FIXME: Multiple streams per file for e.g. resource forks
// ctx->dokan_operations.FindStreams = kbfsLibdokanC_FindStreams;
return ctx;
}
void kbfsLibdokanSet_path(struct kbfsLibdokanCtx* ctx, void* ptr) {
if(ctx->dokan_options.MountPoint)
free((void*)ctx->dokan_options.MountPoint);
ctx->dokan_options.MountPoint = wcsdup(ptr);
}
error_t kbfsLibdokanFree(struct kbfsLibdokanCtx* ctx) {
if(ctx) {
if(ctx->dokan_options.MountPoint)
free((void*)ctx->dokan_options.MountPoint);
free(ctx);
}
return 0;
}
error_t kbfsLibdokanRun(struct kbfsLibdokanCtx* ctx) {
if(!kbfsLibdokanPtr_Main)
kbfsLibdokanLoadLibrary(NULL);
if(!kbfsLibdokanPtr_Main)
return kbfsLibDokan_DLL_LOAD_ERROR;
if((ctx->dokan_options.Options & kbfsLibdokanUseFindFilesWithPattern) != 0) {
ctx->dokan_options.Options &= ~kbfsLibdokanUseFindFilesWithPattern;
ctx->dokan_operations.FindFilesWithPattern = kbfsLibdokanC_FindFilesWithPattern;
}
int status = (*kbfsLibdokanPtr_Main)(&ctx->dokan_options, &ctx->dokan_operations);
return status;
}
int kbfsLibdokanFill_find(PFillFindData fptr, PWIN32_FIND_DATAW a1, PDOKAN_FILE_INFO a2) {
return fptr(a1, a2);
}
BOOL kbfsLibdokan_RemoveMountPoint(LPCWSTR MountPoint) {
if(!kbfsLibdokanPtr_RemoveMountPoint)
return 0;
return (*kbfsLibdokanPtr_RemoveMountPoint)(MountPoint);
}
HANDLE kbfsLibdokan_OpenRequestorToken(PDOKAN_FILE_INFO DokanFileInfo) {
if(!kbfsLibdokanPtr_OpenRequestorToken)
return INVALID_HANDLE_VALUE;
return (*kbfsLibdokanPtr_OpenRequestorToken)(DokanFileInfo);
}
#endif /* windows check */