2 Unix SMB/CIFS implementation.
3 default IPC$ NTVFS backend
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Stefan (metze) Metzmacher 2004-2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 this implements the IPC$ backend, called by the NTVFS subsystem to
23 handle requests on IPC$ shares
28 #include "lib/util/dlinklist.h"
29 #include "ntvfs/ntvfs.h"
30 #include "libcli/rap/rap.h"
31 #include "ntvfs/ipc/proto.h"
32 #include "rpc_server/dcerpc_server.h"
33 #include "libcli/raw/ioctl.h"
35 /* this is the private structure used to keep the state of an open
36 ipc$ connection. It needs to keep information about all open
39 struct ntvfs_module_context *ntvfs;
41 struct dcesrv_context *dcesrv;
43 /* a list of open pipes */
45 struct pipe_state *next, *prev;
46 struct ipc_private *private;
47 const char *pipe_name;
48 struct ntvfs_handle *handle;
49 struct dcesrv_connection *dce_conn;
56 find a open pipe give a file handle
58 static struct pipe_state *pipe_state_find(struct ipc_private *private, struct ntvfs_handle *handle)
63 p = ntvfs_handle_get_backend_data(handle, private->ntvfs);
66 s = talloc_get_type(p, struct pipe_state);
73 find a open pipe give a wire fnum
75 static struct pipe_state *pipe_state_find_key(struct ipc_private *private, struct ntvfs_request *req, const DATA_BLOB *key)
77 struct ntvfs_handle *h;
79 h = ntvfs_handle_search_by_wire_key(private->ntvfs, req, key);
82 return pipe_state_find(private, h);
87 connect to a share - always works
89 static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
90 struct ntvfs_request *req, const char *sharename)
93 struct ipc_private *private;
95 ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "IPC");
96 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
98 ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "IPC");
99 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
101 /* prepare the private state for this connection */
102 private = talloc(ntvfs, struct ipc_private);
103 NT_STATUS_HAVE_NO_MEMORY(private);
105 ntvfs->private_data = private;
107 private->ntvfs = ntvfs;
108 private->pipe_list = NULL;
110 /* setup the DCERPC server subsystem */
111 status = dcesrv_init_ipc_context(private, &private->dcesrv);
112 NT_STATUS_NOT_OK_RETURN(status);
118 disconnect from a share
120 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs)
128 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
129 struct ntvfs_request *req,
130 union smb_unlink *unl)
132 return NT_STATUS_ACCESS_DENIED;
136 check if a directory exists
138 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
139 struct ntvfs_request *req,
140 union smb_chkpath *cp)
142 return NT_STATUS_ACCESS_DENIED;
146 return info on a pathname
148 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
149 struct ntvfs_request *req, union smb_fileinfo *info)
151 switch (info->generic.level) {
152 case RAW_FILEINFO_GENERIC:
153 return NT_STATUS_INVALID_DEVICE_REQUEST;
154 case RAW_FILEINFO_GETATTR:
155 return NT_STATUS_ACCESS_DENIED;
157 return ntvfs_map_qpathinfo(ntvfs, req, info);
162 set info on a pathname
164 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
165 struct ntvfs_request *req, union smb_setfileinfo *st)
167 return NT_STATUS_ACCESS_DENIED;
172 destroy a open pipe structure
174 static int ipc_fd_destructor(struct pipe_state *p)
176 DLIST_REMOVE(p->private->pipe_list, p);
180 static struct socket_address *ipc_get_my_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
182 struct ipc_private *private = dce_conn->transport.private_data;
184 return ntvfs_get_my_addr(private->ntvfs, mem_ctx);
187 static struct socket_address *ipc_get_peer_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
189 struct ipc_private *private = dce_conn->transport.private_data;
191 return ntvfs_get_peer_addr(private->ntvfs, mem_ctx);
195 open a file backend - used for MSRPC pipes
197 static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
198 struct ntvfs_request *req, const char *fname,
199 struct pipe_state **ps)
201 struct pipe_state *p;
203 struct dcerpc_binding *ep_description;
204 struct ipc_private *private = ntvfs->private_data;
205 struct ntvfs_handle *h;
207 status = ntvfs_handle_new(ntvfs, req, &h);
208 NT_STATUS_NOT_OK_RETURN(status);
210 p = talloc(h, struct pipe_state);
211 NT_STATUS_HAVE_NO_MEMORY(p);
213 ep_description = talloc(req, struct dcerpc_binding);
214 NT_STATUS_HAVE_NO_MEMORY(ep_description);
216 while (fname[0] == '\\') fname++;
218 p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
219 NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
222 p->ipc_state = 0x5ff;
225 we're all set, now ask the dcerpc server subsystem to open the
226 endpoint. At this stage the pipe isn't bound, so we don't
227 know what interface the user actually wants, just that they want
228 one of the interfaces attached to this pipe endpoint.
230 ep_description->transport = NCACN_NP;
231 ep_description->endpoint = talloc_reference(ep_description, p->pipe_name);
233 /* The session info is refcount-increased in the
234 * dcesrv_endpoint_search_connect() function
236 status = dcesrv_endpoint_search_connect(private->dcesrv,
240 ntvfs->ctx->event_ctx,
242 ntvfs->ctx->server_id,
245 NT_STATUS_NOT_OK_RETURN(status);
247 p->dce_conn->transport.private_data = private;
248 p->dce_conn->transport.report_output_data = NULL;
249 p->dce_conn->transport.get_my_addr = ipc_get_my_addr;
250 p->dce_conn->transport.get_peer_addr = ipc_get_peer_addr;
252 DLIST_ADD(private->pipe_list, p);
254 p->private = private;
256 talloc_set_destructor(p, ipc_fd_destructor);
258 status = ntvfs_handle_set_backend_data(h, private->ntvfs, p);
259 NT_STATUS_NOT_OK_RETURN(status);
266 open a file with ntcreatex - used for MSRPC pipes
268 static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
269 struct ntvfs_request *req, union smb_open *oi)
271 struct pipe_state *p;
274 status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
275 if (!NT_STATUS_IS_OK(status)) {
279 ZERO_STRUCT(oi->ntcreatex.out);
280 oi->ntcreatex.out.file.ntvfs= p->handle;
281 oi->ntcreatex.out.ipc_state = p->ipc_state;
282 oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
288 open a file with openx - used for MSRPC pipes
290 static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
291 struct ntvfs_request *req, union smb_open *oi)
293 struct pipe_state *p;
295 const char *fname = oi->openx.in.fname;
297 status = ipc_open_generic(ntvfs, req, fname, &p);
298 if (!NT_STATUS_IS_OK(status)) {
302 ZERO_STRUCT(oi->openx.out);
303 oi->openx.out.file.ntvfs= p->handle;
304 oi->openx.out.ftype = 2;
305 oi->openx.out.devstate = p->ipc_state;
311 open a file with SMB2 Create - used for MSRPC pipes
313 static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
314 struct ntvfs_request *req, union smb_open *oi)
316 struct pipe_state *p;
319 status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
320 NT_STATUS_NOT_OK_RETURN(status);
322 oi->smb2.out.file.ntvfs = p->handle;
323 oi->smb2.out.oplock_flags = oi->smb2.in.oplock_flags;
324 oi->smb2.out.create_action = NTCREATEX_ACTION_EXISTED;
325 oi->smb2.out.create_time = 0;
326 oi->smb2.out.access_time = 0;
327 oi->smb2.out.write_time = 0;
328 oi->smb2.out.change_time = 0;
329 oi->smb2.out.alloc_size = 4096;
330 oi->smb2.out.size = 0;
331 oi->smb2.out.file_attr = FILE_ATTRIBUTE_NORMAL;
332 oi->smb2.out._pad = 0;
333 oi->smb2.out.blob = data_blob(NULL, 0);
339 open a file - used for MSRPC pipes
341 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
342 struct ntvfs_request *req, union smb_open *oi)
346 switch (oi->generic.level) {
347 case RAW_OPEN_NTCREATEX:
348 status = ipc_open_ntcreatex(ntvfs, req, oi);
351 status = ipc_open_openx(ntvfs, req, oi);
354 status = ipc_open_smb2(ntvfs, req, oi);
357 status = NT_STATUS_NOT_SUPPORTED;
367 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
368 struct ntvfs_request *req, union smb_mkdir *md)
370 return NT_STATUS_ACCESS_DENIED;
376 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
377 struct ntvfs_request *req, struct smb_rmdir *rd)
379 return NT_STATUS_ACCESS_DENIED;
383 rename a set of files
385 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
386 struct ntvfs_request *req, union smb_rename *ren)
388 return NT_STATUS_ACCESS_DENIED;
394 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
395 struct ntvfs_request *req, struct smb_copy *cp)
397 return NT_STATUS_ACCESS_DENIED;
400 static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
402 DATA_BLOB *blob = private_data;
404 if (out->length < blob->length) {
405 blob->length = out->length;
407 memcpy(blob->data, out->data, blob->length);
408 *nwritten = blob->length;
415 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
416 struct ntvfs_request *req, union smb_read *rd)
418 struct ipc_private *private = ntvfs->private_data;
420 struct pipe_state *p;
421 NTSTATUS status = NT_STATUS_OK;
423 if (rd->generic.level != RAW_READ_GENERIC) {
424 return ntvfs_map_read(ntvfs, req, rd);
427 p = pipe_state_find(private, rd->readx.in.file.ntvfs);
429 return NT_STATUS_INVALID_HANDLE;
432 data.length = rd->readx.in.maxcnt;
433 data.data = rd->readx.out.data;
434 if (data.length > UINT16_MAX) {
435 data.length = UINT16_MAX;
438 if (data.length != 0) {
439 status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
440 if (NT_STATUS_IS_ERR(status)) {
445 rd->readx.out.remaining = 0;
446 rd->readx.out.compaction_mode = 0;
447 rd->readx.out.nread = data.length;
455 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
456 struct ntvfs_request *req, union smb_write *wr)
458 struct ipc_private *private = ntvfs->private_data;
460 struct pipe_state *p;
463 if (wr->generic.level != RAW_WRITE_GENERIC) {
464 return ntvfs_map_write(ntvfs, req, wr);
467 data.data = discard_const_p(void, wr->writex.in.data);
468 data.length = wr->writex.in.count;
470 p = pipe_state_find(private, wr->writex.in.file.ntvfs);
472 return NT_STATUS_INVALID_HANDLE;
475 status = dcesrv_input(p->dce_conn, &data);
476 if (!NT_STATUS_IS_OK(status)) {
480 wr->writex.out.nwritten = data.length;
481 wr->writex.out.remaining = 0;
489 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
490 struct ntvfs_request *req,
493 return NT_STATUS_ACCESS_DENIED;
499 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
500 struct ntvfs_request *req,
503 return NT_STATUS_ACCESS_DENIED;
509 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
510 struct ntvfs_request *req, union smb_close *io)
512 struct ipc_private *private = ntvfs->private_data;
513 struct pipe_state *p;
515 if (io->generic.level != RAW_CLOSE_CLOSE) {
516 return ntvfs_map_close(ntvfs, req, io);
519 p = pipe_state_find(private, io->close.in.file.ntvfs);
521 return NT_STATUS_INVALID_HANDLE;
532 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
533 struct ntvfs_request *req)
535 struct ipc_private *private = ntvfs->private_data;
536 struct pipe_state *p, *next;
538 for (p=private->pipe_list; p; p=next) {
540 if (p->handle->session_info == req->session_info &&
541 p->handle->smbpid == req->smbpid) {
550 logoff - closing files open by the user
552 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
553 struct ntvfs_request *req)
555 struct ipc_private *private = ntvfs->private_data;
556 struct pipe_state *p, *next;
558 for (p=private->pipe_list; p; p=next) {
560 if (p->handle->session_info == req->session_info) {
569 setup for an async call
571 static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
572 struct ntvfs_request *req,
581 static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs,
582 struct ntvfs_request *req)
584 return NT_STATUS_UNSUCCESSFUL;
590 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
591 struct ntvfs_request *req, union smb_lock *lck)
593 return NT_STATUS_ACCESS_DENIED;
597 set info on a open file
599 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
600 struct ntvfs_request *req, union smb_setfileinfo *info)
602 return NT_STATUS_ACCESS_DENIED;
606 query info on a open file
608 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
609 struct ntvfs_request *req, union smb_fileinfo *info)
611 struct ipc_private *private = ntvfs->private_data;
612 struct pipe_state *p = pipe_state_find(private, info->generic.in.file.ntvfs);
614 return NT_STATUS_INVALID_HANDLE;
616 switch (info->generic.level) {
617 case RAW_FILEINFO_GENERIC:
619 ZERO_STRUCT(info->generic.out);
620 info->generic.out.attrib = FILE_ATTRIBUTE_NORMAL;
621 info->generic.out.fname.s = strrchr(p->pipe_name, '\\');
622 info->generic.out.alloc_size = 4096;
623 info->generic.out.nlink = 1;
624 /* What the heck? Match Win2k3: IPC$ pipes are delete pending */
625 info->generic.out.delete_pending = 1;
628 case RAW_FILEINFO_ALT_NAME_INFO:
629 case RAW_FILEINFO_ALT_NAME_INFORMATION:
630 case RAW_FILEINFO_STREAM_INFO:
631 case RAW_FILEINFO_STREAM_INFORMATION:
632 case RAW_FILEINFO_COMPRESSION_INFO:
633 case RAW_FILEINFO_COMPRESSION_INFORMATION:
634 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
635 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
636 return NT_STATUS_INVALID_PARAMETER;
637 case RAW_FILEINFO_ALL_EAS:
638 return NT_STATUS_ACCESS_DENIED;
640 return ntvfs_map_qfileinfo(ntvfs, req, info);
643 return NT_STATUS_ACCESS_DENIED;
648 return filesystem info
650 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
651 struct ntvfs_request *req, union smb_fsinfo *fs)
653 return NT_STATUS_ACCESS_DENIED;
657 return print queue info
659 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
660 struct ntvfs_request *req, union smb_lpq *lpq)
662 return NT_STATUS_ACCESS_DENIED;
666 list files in a directory matching a wildcard pattern
668 static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
669 struct ntvfs_request *req, union smb_search_first *io,
670 void *search_private,
671 BOOL (*callback)(void *, const union smb_search_data *))
673 return NT_STATUS_ACCESS_DENIED;
677 continue listing files in a directory
679 static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
680 struct ntvfs_request *req, union smb_search_next *io,
681 void *search_private,
682 BOOL (*callback)(void *, const union smb_search_data *))
684 return NT_STATUS_ACCESS_DENIED;
688 end listing files in a directory
690 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
691 struct ntvfs_request *req, union smb_search_close *io)
693 return NT_STATUS_ACCESS_DENIED;
696 static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
698 NTSTATUS status = NT_STATUS_OK;
699 DATA_BLOB *blob = private_data;
701 if (out->length > blob->length) {
702 status = STATUS_BUFFER_OVERFLOW;
705 if (out->length < blob->length) {
706 blob->length = out->length;
708 memcpy(blob->data, out->data, blob->length);
709 *nwritten = blob->length;
713 /* SMBtrans - handle a DCERPC command */
714 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
715 struct ntvfs_request *req, struct smb_trans2 *trans)
717 struct pipe_state *p;
718 struct ipc_private *private = ntvfs->private_data;
724 * the fnum is in setup[1], a 16 bit value
725 * the setup[*] values are already in host byteorder
726 * but ntvfs_handle_search_by_wire_key() expects
729 SSVAL(&fnum, 0, trans->in.setup[1]);
730 fnum_key = data_blob_const(&fnum, 2);
732 p = pipe_state_find_key(private, req, &fnum_key);
734 return NT_STATUS_INVALID_HANDLE;
737 trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
738 if (!trans->out.data.data) {
739 return NT_STATUS_NO_MEMORY;
742 /* pass the data to the dcerpc server. Note that we don't
743 expect this to fail, and things like NDR faults are not
744 reported at this stage. Those sorts of errors happen in the
745 dcesrv_output stage */
746 status = dcesrv_input(p->dce_conn, &trans->in.data);
747 if (!NT_STATUS_IS_OK(status)) {
752 now ask the dcerpc system for some output. This doesn't yet handle
753 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
754 the error is encoded at the dcerpc level
756 status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
757 if (NT_STATUS_IS_ERR(status)) {
761 trans->out.setup_count = 0;
762 trans->out.setup = NULL;
763 trans->out.params = data_blob(NULL, 0);
769 /* SMBtrans - set named pipe state */
770 static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
771 struct ntvfs_request *req, struct smb_trans2 *trans)
773 struct ipc_private *private = ntvfs->private_data;
774 struct pipe_state *p;
777 /* the fnum is in setup[1] */
778 fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1]));
780 p = pipe_state_find_key(private, req, &fnum_key);
782 return NT_STATUS_INVALID_HANDLE;
785 if (trans->in.params.length != 2) {
786 return NT_STATUS_INVALID_PARAMETER;
788 p->ipc_state = SVAL(trans->in.params.data, 0);
790 trans->out.setup_count = 0;
791 trans->out.setup = NULL;
792 trans->out.params = data_blob(NULL, 0);
793 trans->out.data = data_blob(NULL, 0);
799 /* SMBtrans - used to provide access to SMB pipes */
800 static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
801 struct ntvfs_request *req, struct smb_trans2 *trans)
805 if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
806 return ipc_rap_call(req, trans);
808 if (trans->in.setup_count != 2) {
809 return NT_STATUS_INVALID_PARAMETER;
812 switch (trans->in.setup[0]) {
813 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
814 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
816 case TRANSACT_DCERPCCMD:
817 status = ipc_dcerpc_cmd(ntvfs, req, trans);
820 status = NT_STATUS_INVALID_PARAMETER;
827 static NTSTATUS ipc_ioctl_smb2(struct ntvfs_module_context *ntvfs,
828 struct ntvfs_request *req, union smb_ioctl *io)
830 struct pipe_state *p;
831 struct ipc_private *private = ntvfs->private_data;
834 switch (io->smb2.in.function) {
835 case FSCTL_NAMED_PIPE_READ_WRITE:
839 return NT_STATUS_FS_DRIVER_REQUIRED;
842 p = pipe_state_find(private, io->smb2.in.file.ntvfs);
844 return NT_STATUS_INVALID_HANDLE;
847 io->smb2.out.out = data_blob_talloc(req, NULL, io->smb2.in.max_response_size);
848 NT_STATUS_HAVE_NO_MEMORY(io->smb2.out.out.data);
850 /* pass the data to the dcerpc server. Note that we don't
851 expect this to fail, and things like NDR faults are not
852 reported at this stage. Those sorts of errors happen in the
853 dcesrv_output stage */
854 status = dcesrv_input(p->dce_conn, &io->smb2.in.out);
855 NT_STATUS_NOT_OK_RETURN(status);
858 now ask the dcerpc system for some output. This doesn't yet handle
859 async calls. Again, we only expect NT_STATUS_OK. If the call fails then
860 the error is encoded at the dcerpc level
862 status = dcesrv_output(p->dce_conn, &io->smb2.out.out, ipc_trans_dcesrv_output);
863 NT_STATUS_IS_ERR_RETURN(status);
865 io->smb2.out._pad = 0;
866 io->smb2.out.function = io->smb2.in.function;
867 io->smb2.out.unknown2 = 0;
868 io->smb2.out.unknown3 = 0;
869 io->smb2.out.in = io->smb2.in.out;
877 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
878 struct ntvfs_request *req, union smb_ioctl *io)
880 switch (io->generic.level) {
882 return ipc_ioctl_smb2(ntvfs, req, io);
884 case RAW_IOCTL_SMB2_NO_HANDLE:
885 return NT_STATUS_FS_DRIVER_REQUIRED;
888 return NT_STATUS_ACCESS_DENIED;
891 return NT_STATUS_ACCESS_DENIED;
896 initialialise the IPC backend, registering ourselves with the ntvfs subsystem
898 NTSTATUS ntvfs_ipc_init(void)
901 struct ntvfs_ops ops;
902 NTVFS_CURRENT_CRITICAL_SIZES(vers);
906 /* fill in the name and type */
907 ops.name = "default";
908 ops.type = NTVFS_IPC;
910 /* fill in all the operations */
911 ops.connect = ipc_connect;
912 ops.disconnect = ipc_disconnect;
913 ops.unlink = ipc_unlink;
914 ops.chkpath = ipc_chkpath;
915 ops.qpathinfo = ipc_qpathinfo;
916 ops.setpathinfo = ipc_setpathinfo;
918 ops.mkdir = ipc_mkdir;
919 ops.rmdir = ipc_rmdir;
920 ops.rename = ipc_rename;
922 ops.ioctl = ipc_ioctl;
924 ops.write = ipc_write;
926 ops.flush = ipc_flush;
927 ops.close = ipc_close;
930 ops.setfileinfo = ipc_setfileinfo;
931 ops.qfileinfo = ipc_qfileinfo;
932 ops.fsinfo = ipc_fsinfo;
934 ops.search_first = ipc_search_first;
935 ops.search_next = ipc_search_next;
936 ops.search_close = ipc_search_close;
937 ops.trans = ipc_trans;
938 ops.logoff = ipc_logoff;
939 ops.async_setup = ipc_async_setup;
940 ops.cancel = ipc_cancel;
942 /* register ourselves with the NTVFS subsystem. */
943 ret = ntvfs_register(&ops, &vers);
945 if (!NT_STATUS_IS_OK(ret)) {
946 DEBUG(0,("Failed to register IPC backend!\n"));