Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

502 lines
13 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. pipe.c
  5. Abstract:
  6. Implements initialization and pipe interface for rudimentary quorum access server
  7. Author:
  8. Gor Nishanov (gorn) 20-Sep-2001
  9. Revision History:
  10. --*/
  11. #define UNICODE 1
  12. #include <nt.h>
  13. #include <ntdef.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <stdlib.h>
  18. #include "fs.h"
  19. #include "pipe.h"
  20. #include "QfsTrans.h"
  21. #include "clusrtl.h"
  22. typedef struct _PIPECTX_ {
  23. CRITICAL_SECTION cs;
  24. LUID me;
  25. USHORT uid;
  26. USHORT tid;
  27. PVOID user;
  28. FsDispatchTable *pDisp;
  29. LPWSTR share;
  30. PVOID FsCtx;
  31. PVOID resHdl;
  32. int nThreads;
  33. HANDLE* hThreads;
  34. SHARED_MEM_SERVER MemServer;
  35. LONG NeedsCleanup;
  36. } PipeCtx_t;
  37. typedef DWORD (*PipeDispatch_t)(PipeCtx_t* ctx, JobBuf_t* job);
  38. // QFSP_INSERT_OP_NAMES defined in QfsTrans
  39. // it is used here to generate human readable
  40. // operation names
  41. #define OPNAME(Name) "op" #Name,
  42. char* OpNames[] = {
  43. QFSP_INSERT_OP_NAMES
  44. };
  45. #undef OPNAME
  46. // QFSP_INSERT_OP_NAMES defined in QfsTrans
  47. // it is used here to generate forward declarations of operation handlers
  48. #define OPNAME(Name) extern DWORD Qfsp ## Name(PipeCtx_t* ctx, JobBuf_t* job);
  49. QFSP_INSERT_OP_NAMES
  50. #undef OPNAME
  51. // QFSP_INSERT_OP_NAMES defined in QfsTrans
  52. // it is used here to generate array of operation handlers
  53. #define OPNAME(Name) Qfsp ## Name,
  54. PipeDispatch_t OpDispatch[] =
  55. {
  56. QFSP_INSERT_OP_NAMES
  57. };
  58. #undef OPNAME
  59. #define LogError(_x_) EPRINT(_x_)
  60. #define Log(_x_) DPRINT(_x_)
  61. #undef malloc
  62. #undef free
  63. #define malloc(dwBytes) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes)
  64. #define free(hHeap) HeapFree(GetProcessHeap(), 0, hHeap)
  65. DWORD
  66. PipeInit(PVOID resHdl, PVOID fsHdl, PVOID *Hdl)
  67. {
  68. PipeCtx_t *ctx;
  69. DWORD err;
  70. ctx = (PipeCtx_t *) malloc(sizeof(*ctx));
  71. if (ctx == NULL) {
  72. return ERROR_NOT_ENOUGH_MEMORY;
  73. }
  74. memset(ctx, 0, sizeof(*ctx));
  75. if (!AllocateLocallyUniqueId(&ctx->me)) {
  76. free(ctx);
  77. LogError(("PipeInit, failed to allocate LUID, error %d\n", GetLastError()));
  78. return GetLastError();
  79. }
  80. ctx->FsCtx = fsHdl;
  81. ctx->resHdl = resHdl;
  82. InitializeCriticalSection(&ctx->cs);
  83. *Hdl = (PVOID) ctx;
  84. return ERROR_SUCCESS;
  85. }
  86. void
  87. PipeExit(PVOID Hdl)
  88. {
  89. PipeCtx_t *ctx = (PipeCtx_t *) Hdl;
  90. if (ctx != NULL) {
  91. DeleteCriticalSection(&ctx->cs);
  92. free(ctx);
  93. }
  94. }
  95. VOID MemServer_Dispatch(PJOB_BUF buf, PVOID Hdl)
  96. {
  97. PipeCtx_t *ctx = (PipeCtx_t *) Hdl;
  98. if (buf->hdr.OpCode >= OpCount) {
  99. LogError(("bad opcode %d\n", buf->hdr.OpCode));
  100. buf->hdr.Status = ERROR_INVALID_FUNCTION;
  101. } else {
  102. Log(("enter %s... \n", OpNames[buf->hdr.OpCode]));
  103. buf->hdr.Status = OpDispatch[buf->hdr.OpCode](ctx, buf);
  104. Log(("exit %s => %d\n", OpNames[buf->hdr.OpCode], buf->hdr.Status));
  105. buf->hdr.OpCode = opNone;
  106. }
  107. }
  108. #define NUM_BUFFERS 8
  109. DWORD PipeOnline(PVOID Hdl, LPWSTR Path)
  110. {
  111. PipeCtx_t *ctx = (PipeCtx_t *) Hdl;
  112. int nThreads = 0;
  113. int i;
  114. WCHAR* lastSlash = wcsrchr(Path, '\\');
  115. DWORD Status = ERROR_SUCCESS;
  116. ctx->share = Path;
  117. if (lastSlash) {
  118. Path = lastSlash+1;
  119. }
  120. Log(("PipeOnline. Path \"%ws\" Share \"%ws\"\n", ctx->share, Path));
  121. FsLogonUser(ctx->FsCtx, NULL, ctx->me, &ctx->uid);
  122. FsMount(ctx->FsCtx, Path, ctx->uid, &ctx->tid);
  123. ctx->pDisp = FsGetHandle(ctx->FsCtx, ctx->tid, ctx->uid, &ctx->user);
  124. if (!ctx->pDisp) {
  125. return ERROR_FILE_NOT_FOUND;
  126. }
  127. // This should be done after registering with FS.
  128. Status = MemServer_Online(
  129. &ctx->MemServer, NUM_BUFFERS,
  130. MemServer_Dispatch, Hdl);
  131. if (Status != ERROR_SUCCESS) {
  132. FsDisMount(ctx->FsCtx, ctx->uid, ctx->tid);
  133. FsLogoffUser(ctx->FsCtx, ctx->me);
  134. return Status;
  135. }
  136. ctx->NeedsCleanup = TRUE;
  137. return ERROR_SUCCESS;
  138. }
  139. DWORD PipeOffline(PVOID Hdl)
  140. {
  141. PipeCtx_t *ctx = (PipeCtx_t *) Hdl;
  142. if (InterlockedExchange(&ctx->NeedsCleanup, FALSE) == TRUE) {
  143. MemServer_Offline(&ctx->MemServer);
  144. FsDisMount(ctx->FsCtx, ctx->uid, ctx->tid);
  145. FsLogoffUser(ctx->FsCtx, ctx->me);
  146. }
  147. return ERROR_SUCCESS;
  148. }
  149. #define QfsHandleToWin32Handle(hdl) ((HANDLE)(hdl))
  150. USHORT Win32HandleToQfsHandle(HANDLE hFile)
  151. {
  152. ULONG_PTR u = (ULONG_PTR)hFile;
  153. if (u > 0xffff) {
  154. LogError(("pipe: Invalid Win32 handle passed 0x%x\n", u));
  155. return INVALID_FHANDLE_T;
  156. }
  157. return (USHORT) (u);
  158. }
  159. /////////////////////////////////////////////////////////////
  160. // operation handler routines
  161. // given a JobBuf calls appropriate Fs routines
  162. /////////////////////////////////////////////////////////////
  163. DWORD QfspCreateFile(
  164. PipeCtx_t *ctx,
  165. JobBuf_t* j)
  166. {
  167. DWORD error;
  168. DWORD flags = 0;
  169. fattr_t attr;
  170. fhandle_t hdl;
  171. ZeroMemory(&attr, sizeof(attr));
  172. if (j->dwFlagsAndAttributes & FILE_ATTRIBUTE_READONLY) attr.attributes |= ATTR_READONLY;
  173. if (j->dwFlagsAndAttributes & FILE_ATTRIBUTE_HIDDEN) attr.attributes |= ATTR_HIDDEN;
  174. if (j->dwFlagsAndAttributes & FILE_ATTRIBUTE_SYSTEM) attr.attributes |= ATTR_SYSTEM;
  175. if (j->dwFlagsAndAttributes & FILE_ATTRIBUTE_ARCHIVE) attr.attributes |= ATTR_ARCHIVE;
  176. if (j->dwFlagsAndAttributes & FILE_ATTRIBUTE_DIRECTORY) attr.attributes |= ATTR_DIRECTORY;
  177. if (j->dwFlagsAndAttributes & FILE_ATTRIBUTE_COMPRESSED) attr.attributes |= ATTR_COMPRESSED;
  178. if (j->dwFlagsAndAttributes & FILE_ATTRIBUTE_OFFLINE) attr.attributes |= ATTR_OFFLINE;
  179. if (j->dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING) flags |= CACHE_NO_BUFFERING;
  180. if (j->dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH) flags |= CACHE_WRITE_THROUGH;
  181. switch (j->dwCreationDisposition) {
  182. case CREATE_NEW: flags |= DISP_CREATE_NEW; break;
  183. case CREATE_ALWAYS: flags |= DISP_CREATE_ALWAYS; break;
  184. case OPEN_EXISTING: flags |= DISP_OPEN_EXISTING; break;
  185. case OPEN_ALWAYS: flags |= DISP_OPEN_ALWAYS; break;
  186. case TRUNCATE_EXISTING: flags |= DISP_TRUNCATE_EXISTING; break;
  187. }
  188. if(j->dwShareMode & FILE_SHARE_READ) flags |= SHARE_READ;
  189. if(j->dwShareMode & FILE_SHARE_WRITE) flags |= SHARE_WRITE;
  190. if(j->dwDesiredAccess & GENERIC_READ) flags |= ACCESS_READ;
  191. if(j->dwDesiredAccess & GENERIC_WRITE) flags |= ACCESS_WRITE;
  192. LogError(("Flags %x\n", flags));
  193. error = ctx->pDisp->FsCreate(
  194. ctx->user,
  195. j->FileName,
  196. (USHORT)wcslen(j->FileName),
  197. flags,
  198. &attr,
  199. &hdl,
  200. &j->dwCreationDisposition);
  201. if (error != ERROR_SUCCESS) {
  202. j->Handle = INVALID_HANDLE_VALUE;
  203. } else {
  204. j->Handle = QfsHandleToWin32Handle(hdl);
  205. *FsGetFilePointerFromHandle(ctx->user, hdl) = 0;
  206. switch (j->dwCreationDisposition & 0x7) {
  207. case FILE_CREATE: j->dwCreationDisposition = CREATE_NEW; break;
  208. case FILE_OPEN: j->dwCreationDisposition = OPEN_EXISTING; break;
  209. default: j->dwCreationDisposition = 0;
  210. }
  211. }
  212. return error;
  213. }
  214. DWORD QfspCloseFile(
  215. PipeCtx_t *ctx,
  216. JobBuf_t* j)
  217. {
  218. return ctx->pDisp->FsClose(ctx->user, Win32HandleToQfsHandle(j->Handle));
  219. }
  220. DWORD QfspNone(
  221. PipeCtx_t *ctx,
  222. JobBuf_t* j)
  223. {
  224. return ERROR_SUCCESS;
  225. }
  226. DWORD QfspReadFile(
  227. PipeCtx_t *ctx,
  228. JobBuf_t* j)
  229. {
  230. DWORD Status;
  231. fhandle_t hdl = Win32HandleToQfsHandle(j->Handle);
  232. if(j->Offset == (ULONGLONG)-1) {
  233. j->Offset = *FsGetFilePointerFromHandle(ctx->user, hdl);
  234. }
  235. Status = ctx->pDisp->FsRead(
  236. ctx->user,
  237. hdl,
  238. (UINT32)j->Offset,
  239. &j->cbSize,
  240. j->Buffer,
  241. NULL);
  242. if (Status == ERROR_SUCCESS) {
  243. j->Offset += j->cbSize;
  244. *FsGetFilePointerFromHandle(ctx->user, hdl) = (UINT32)j->Offset;
  245. }
  246. return Status;
  247. }
  248. DWORD QfspWriteFile(
  249. PipeCtx_t *ctx,
  250. JobBuf_t* j)
  251. {
  252. DWORD Status;
  253. fhandle_t hdl = Win32HandleToQfsHandle(j->Handle);
  254. if(j->Offset == ~0) {
  255. j->Offset = *FsGetFilePointerFromHandle(ctx->user, hdl);
  256. }
  257. Status = ctx->pDisp->FsWrite(
  258. ctx->user,
  259. hdl,
  260. (UINT32)j->Offset,
  261. &j->cbSize,
  262. j->Buffer,
  263. NULL);
  264. if (Status == ERROR_SUCCESS) {
  265. j->Offset += j->cbSize;
  266. *FsGetFilePointerFromHandle(ctx->user, hdl) = (UINT32)j->Offset;
  267. }
  268. return Status;
  269. }
  270. DWORD QfspFlushFile(
  271. PipeCtx_t *ctx,
  272. JobBuf_t* j)
  273. {
  274. return ctx->pDisp->FsFlush(
  275. ctx->user,
  276. Win32HandleToQfsHandle(j->Handle));
  277. }
  278. DWORD QfspDeleteFile(
  279. PipeCtx_t *ctx,
  280. JobBuf_t* j)
  281. {
  282. return ctx->pDisp->FsRemove(
  283. ctx->user,
  284. j->FileName,
  285. (USHORT)wcslen(j->FileName) );
  286. }
  287. DWORD QfspCreateDir(
  288. PipeCtx_t *ctx,
  289. JobBuf_t* j)
  290. {
  291. return ctx->pDisp->FsMkdir(
  292. ctx->user,
  293. j->FileName,
  294. (USHORT)wcslen(j->FileName),
  295. NULL );
  296. }
  297. // Dir stuff has to be improved
  298. // Currently it is as bad as original srvcom stuff
  299. DWORD QfspFindFirstFile(
  300. PipeCtx_t *ctx,
  301. JobBuf_t* j)
  302. {
  303. DWORD cbDirSize = wcslen(j->FileName);
  304. DWORD Status;
  305. DWORD len;
  306. Status = ctx->pDisp->FsGetRoot(ctx->user, j->FileNameDest);
  307. if (Status != ERROR_SUCCESS) {
  308. return Status;
  309. }
  310. len = wcslen(j->FileNameDest);
  311. if (j->FileName[0] != 0 && j->FileName[0] != '\\' && len > 0 && j->FileNameDest[len-1] != '\\') {
  312. j->FileNameDest[len] = '\\';
  313. ++len;
  314. }
  315. CopyMemory(j->FileNameDest+len, j->FileName, sizeof(WCHAR) * (cbDirSize+1));
  316. j->Handle = FindFirstFileW(j->FileNameDest, &j->FindFileData);
  317. if (j->Handle == INVALID_HANDLE_VALUE) {
  318. Status = GetLastError();
  319. }
  320. Log(("QfspFindFirstFile path %ws, hdl %x status %d\n", j->FileNameDest, j->Handle, Status));
  321. return Status;
  322. }
  323. DWORD QfspFindNextFile(
  324. PipeCtx_t *ctx,
  325. JobBuf_t* j)
  326. {
  327. DWORD Status;
  328. if( FindNextFile(j->Handle, &j->FindFileData) ) {
  329. Status = ERROR_SUCCESS;
  330. } else {
  331. Status = GetLastError();
  332. }
  333. Log(("QfspFindNextFile, status %d\n", Status));
  334. return Status;
  335. }
  336. DWORD QfspFindClose(
  337. PipeCtx_t *ctx,
  338. JobBuf_t* j)
  339. {
  340. if( FindClose(j->Handle) ) {
  341. return ERROR_SUCCESS;
  342. } else {
  343. return GetLastError();
  344. }
  345. }
  346. DWORD QfspGetDiskFreeSpace(
  347. PipeCtx_t *ctx,
  348. JobBuf_t* j)
  349. {
  350. fs_attr_t fsinfo;
  351. DWORD Status = ctx->pDisp->FsStatfs(ctx->user, &fsinfo);
  352. if (Status == ERROR_SUCCESS) {
  353. ULONGLONG bpu = fsinfo.bytes_per_sector * fsinfo.sectors_per_unit;
  354. j->TotalNumberOfFreeBytes = // don't understand quotas
  355. j->FreeBytesAvailable = fsinfo.free_units * bpu;
  356. j->TotalNumberOfBytes = fsinfo.total_units * bpu;
  357. }
  358. return Status;
  359. }
  360. DWORD QfspGetAttr(
  361. PipeCtx_t *ctx,
  362. JobBuf_t* j)
  363. {
  364. fattr_t finfo;
  365. DWORD Status = ctx->pDisp->FsGetAttr(ctx->user, Win32HandleToQfsHandle(j->Handle), &finfo);
  366. if (Status == ERROR_SUCCESS) {
  367. j->EndOfFile = finfo.file_size;
  368. j->AllocationSize = finfo.alloc_size;
  369. j->CreationTime = finfo.create_time;
  370. j->LastAccessTime = finfo.access_time;
  371. j->LastWriteTime = finfo.mod_time;
  372. j->FileAttributes = finfo.attributes;
  373. }
  374. return Status;
  375. }
  376. DWORD QfspSetAttr2(
  377. PipeCtx_t *ctx,
  378. JobBuf_t* j)
  379. {
  380. fattr_t finfo;
  381. extern UINT32 get_attributes(DWORD a);
  382. finfo.file_size = j->EndOfFile;
  383. finfo.alloc_size = j->AllocationSize;
  384. finfo.create_time = j->CreationTime;
  385. finfo.access_time = j->LastAccessTime;
  386. finfo.mod_time = j->LastWriteTime;
  387. finfo.attributes = get_attributes(j->FileAttributes);
  388. return ctx->pDisp->FsSetAttr2(ctx->user, j->FileName, (USHORT)wcslen(j->FileName), &finfo);
  389. }
  390. DWORD QfspRename(
  391. PipeCtx_t *ctx,
  392. JobBuf_t* j)
  393. {
  394. return ctx->pDisp->FsRename(
  395. ctx->user,
  396. j->FileName,
  397. (USHORT)wcslen(j->FileName),
  398. j->FileNameDest,
  399. (USHORT)wcslen(j->FileNameDest) );
  400. }
  401. DWORD QfspConnect(
  402. PipeCtx_t *ctx,
  403. JobBuf_t* j)
  404. {
  405. DWORD Status;
  406. PWCHAR p = ctx->share;
  407. if (*p == '\\' && *++p == '\\') ++p;
  408. if( wcsncmp(p, j->FileName, wcslen(p)) == 0 ) {
  409. Status = ctx->pDisp->FsConnect(ctx->user, j->ClussvcProcessId);
  410. } else {
  411. // This is the correct return value.
  412. Status = ERROR_NO_MATCH;
  413. }
  414. Log(("[Qfs] Connect %ws => %d\n", j->FileName, Status));
  415. return Status;
  416. }