/afsrpc.h
/afsrpc_c.c
/afsrpc_s.c
-
+/ms-srvsvc.h
+/ms-srvsvc_c.c
+/ms-srvsvc_s.c
+/ms-wkssvc.h
+/ms-wkssvc_c.c
+/ms-wkssvc_s.c
$(INCFILEDIR)\smb3.h \
$(INCFILEDIR)\smb_iocons.h \
$(INCFILEDIR)\smb_ioctl.h \
+ $(INCFILEDIR)\smb_rpc.h \
$(INCFILEDIR)\afsrpc.h \
!IFDEF OSICRASH
$(INCFILEDIR)\afsdcrash.h \
$(IDLFILES):afsrpc.idl
midl $(MIDL_FLAGS) $(AFSDEV_AUXMIDLFLAGS) /app_config $?
+ms-srvsvc.h ms-srvsvc_s.c: ms-srvsvc.idl
+ midl /Os ms-srvsvc.idl
+
+ms-wkssvc.h ms-wkssvc_s.c: ms-wkssvc.idl
+ midl /Os ms-wkssvc.idl
+
+$(OUT)\ms-srvsvc_s.obj: ms-srvsvc_s.c
+ $(C2OBJ) /FImsrpc.h /Fo$@ $**
+
+$(OUT)\ms-wkssvc_s.obj: ms-wkssvc_s.c
+ $(C2OBJ) /FImsrpc.h /Fo$@ $**
+
AFSDOBJS=\
$(OUT)\rawops.obj \
$(OUT)\afsd_init.obj \
$(OUT)\smb.obj \
$(OUT)\smb3.obj \
$(OUT)\smb_ioctl.obj \
+ $(OUT)\smb_rpc.obj \
+ $(OUT)\msrpc.obj \
$(OUT)\cm_ioctl.obj \
$(OUT)\cm_daemon.obj \
$(OUT)\cm_aclent.obj \
$(OUT)\cm_freelance.obj \
$(OUT)\afsd_eventlog.obj \
$(OUT)\afsd_flushvol.obj \
- $(OUT)\afsicf.obj
+ $(OUT)\afsicf.obj \
+ $(OUT)\ms-srvsvc_s.obj \
+ $(OUT)\ms-wkssvc_s.obj \
+ $(OUT)\rpc_wkssvc.obj \
+ $(OUT)\rpc_srvsvc.obj \
+ $(OUT)\AFS_component_version_number.obj
$(AFSDOBJS):
install_objs: $(CONF_DLLFILE) $(LANAHELPERLIB) $(OUT)\afsicf.obj
$(COPY) $(OUT)\afsicf.obj $(DESTDIR)\lib
-install_headers: $(IDLFILES) $(INCFILES)
+install_headers: $(IDLFILES) $(INCFILES) ms-wkssvc.h ms-srvsvc.h
install: install_headers install_objs $(CONF_DLLFILE) \
$(EXEDIR)\klog.exe \
#include "lanahelper.h"
#include <strsafe.h>
#include "cm_memmap.h"
+#include "msrpc.h"
#ifdef DEBUG
#include <crtdbg.h>
#endif
/* Initialize the RPC server for session keys */
RpcInit();
+ /* Initialize the RPC server for pipe services */
+ MSRPC_Init();
+
afsd_InitServerPreferences();
return 0;
}
int afsd_ShutdownCM(void)
{
+ MSRPC_Shutdown();
+
cm_ReleaseSCache(cm_data.rootSCachep);
cm_shutdown = 1;
#define CM_ERROR_LOCK_NOT_GRANTED (CM_ERROR_BASE+59)
#define CM_ERROR_NOTINCACHE (CM_ERROR_BASE+60)
#define CM_ERROR_FORCE_DNS_LOOKUP (CM_ERROR_BASE+61)
+#define CM_ERROR_BADFORMAT (CM_ERROR_BASE+62)
+#define CM_ERROR_RPC_MOREDATA (CM_ERROR_BASE+63)
/* Used by cm_FollowMountPoint and cm_FindVolumeByName */
/* And as an index in cm_volume_t */
}
}
+long
+cm_BPlusDirPeekNextEnumEntry(cm_direnum_t *enump, cm_direnum_entry_t **entrypp)
+{
+ if (enump == NULL || entrypp == NULL || enump->next >= enump->count) {
+ if (entrypp)
+ *entrypp = NULL;
+ osi_Log0(afsd_logp, "cm_BPlusDirPeekNextEnumEntry invalid input");
+ return CM_ERROR_INVAL;
+ }
+
+ if (enump->fetchStatus &&
+ !(enump->entry[enump->next].flags & CM_DIRENUM_FLAG_GOT_STATUS))
+ cm_BPlusDirEnumBulkStatNext(enump);
+
+ *entrypp = &enump->entry[enump->next];
+ if ( enump->next == enump->count ) {
+ osi_Log0(afsd_logp, "cm_BPlusDirPeekNextEnumEntry STOPNOW");
+ return CM_ERROR_STOPNOW;
+ }
+ else {
+ osi_Log0(afsd_logp, "cm_BPlusDirPeekNextEnumEntry SUCCESS");
+ return 0;
+ }
+}
+
long
cm_BPlusDirFreeEnumeration(cm_direnum_t *enump)
{
long cm_BPlusDirEnumerate(cm_scache_t *dscp, cm_user_t *userp, cm_req_t *reqp,
afs_uint32 locked, clientchar_t *maskp, afs_uint32 fetchStatus, cm_direnum_t **enumpp);
long cm_BPlusDirNextEnumEntry(cm_direnum_t *enump, cm_direnum_entry_t **entrypp);
+long cm_BPlusDirPeekNextEnumEntry(cm_direnum_t *enump, cm_direnum_entry_t **entrypp);
long cm_BPlusDirFreeEnumeration(cm_direnum_t *enump);
long cm_BPlusDirEnumTest(cm_scache_t * dscp, cm_user_t *userp, cm_req_t *reqp, afs_uint32 locked);
long cm_BPlusDirEnumBulkStat(cm_direnum_t *enump);
--- /dev/null
+/*
+ * Copyright 2009 Microsoft
+ *
+ * Used with permission
+ */
+
+import "wtypes.idl";
+
+typedef unsigned char UCHAR;
+typedef unsigned char *PUCHAR;
+typedef WCHAR *LMSTR;
+typedef DWORD NET_API_STATUS;
+typedef DWORD SECURITY_INFORMATION;
+typedef DWORD *PSECURITY_INFORMATION;
+
+[
+ uuid(4B324FC8-1670-01D3-1278-5A47BF6EE188),
+ version(3.0),
+ ms_union,
+ pointer_default(unique)
+]
+interface srvsvc
+{
+ typedef [handle, string] wchar_t * SRVSVC_HANDLE;
+
+ typedef struct _CONNECTION_INFO_0
+ {
+ DWORD coni0_id;
+ } CONNECTION_INFO_0,
+ *PCONNECTION_INFO_0,
+ *LPCONNECTION_INFO_0;
+
+ typedef struct _CONNECT_INFO_0_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPCONNECTION_INFO_0 Buffer;
+ } CONNECT_INFO_0_CONTAINER,
+ *PCONNECT_INFO_0_CONTAINER,
+ *LPCONNECT_INFO_0_CONTAINER;
+
+ typedef struct _CONNECTION_INFO_1
+ {
+ DWORD coni1_id;
+ DWORD coni1_type;
+ DWORD coni1_num_opens;
+ DWORD coni1_num_users;
+ DWORD coni1_time;
+ [string] wchar_t * coni1_username;
+ [string] wchar_t * coni1_netname;
+ } CONNECTION_INFO_1,
+ *PCONNECTION_INFO_1,
+ *LPCONNECTION_INFO_1;
+
+ typedef struct _CONNECT_INFO_1_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPCONNECTION_INFO_1 Buffer;
+ } CONNECT_INFO_1_CONTAINER,
+ *PCONNECT_INFO_1_CONTAINER,
+ *LPCONNECT_INFO_1_CONTAINER;
+
+ typedef [switch_type(DWORD)] union _CONNECT_ENUM_UNION {
+ [case(0)]
+ CONNECT_INFO_0_CONTAINER* Level0;
+ [case(1)]
+ CONNECT_INFO_1_CONTAINER* Level1;
+ } CONNECT_ENUM_UNION;
+
+ typedef struct _CONNECT_ENUM_STRUCT {
+ DWORD Level;
+ [switch_is(Level)] CONNECT_ENUM_UNION ConnectInfo;
+ } CONNECT_ENUM_STRUCT,
+ *PCONNECT_ENUM_STRUCT,
+ *LPCONNECT_ENUM_STRUCT;
+
+ typedef struct _FILE_INFO_2
+ {
+ DWORD fi2_id;
+ } FILE_INFO_2, *PFILE_INFO_2, *LPFILE_INFO_2;
+
+ typedef struct _FILE_INFO_2_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPFILE_INFO_2 Buffer;
+ } FILE_INFO_2_CONTAINER,
+ *PFILE_INFO_2_CONTAINER,
+ *LPFILE_INFO_2_CONTAINER;
+
+ typedef struct _FILE_INFO_3 {
+ DWORD fi3_id;
+ DWORD fi3_permissions;
+ DWORD fi3_num_locks;
+ [string] wchar_t * fi3_pathname;
+ [string] wchar_t * fi3_username;
+ } FILE_INFO_3,
+ *PFILE_INFO_3,
+ *LPFILE_INFO_3;
+
+ typedef struct _FILE_INFO_3_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPFILE_INFO_3 Buffer;
+ } FILE_INFO_3_CONTAINER,
+ *PFILE_INFO_3_CONTAINER,
+ *LPFILE_INFO_3_CONTAINER;
+
+ typedef [switch_type(DWORD)] union _FILE_ENUM_UNION {
+ [case(2)]
+ FILE_INFO_2_CONTAINER* Level2;
+ [case(3)]
+ FILE_INFO_3_CONTAINER* Level3;
+ } FILE_ENUM_UNION;
+
+ typedef struct _FILE_ENUM_STRUCT {
+ DWORD Level;
+ [switch_is(Level)] FILE_ENUM_UNION FileInfo;
+ } FILE_ENUM_STRUCT,
+ *PFILE_ENUM_STRUCT,
+ *LPFILE_ENUM_STRUCT;
+
+ typedef [switch_type(unsigned long)] union _FILE_INFO
+ {
+ [case(2)]
+ LPFILE_INFO_2 FileInfo2;
+ [case(3)]
+ LPFILE_INFO_3 FileInfo3;
+ } FILE_INFO,
+ *PFILE_INFO,
+ *LPFILE_INFO;
+
+ typedef struct _SESSION_INFO_0
+ {
+ [string] wchar_t * sesi0_cname;
+ } SESSION_INFO_0,
+ *PSESSION_INFO_0,
+ *LPSESSION_INFO_0;
+
+ typedef struct _SESSION_INFO_0_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSESSION_INFO_0 Buffer;
+ } SESSION_INFO_0_CONTAINER,
+ *PSESSION_INFO_0_CONTAINER,
+ *LPSESSION_INFO_0_CONTAINER;
+
+ typedef struct _SESSION_INFO_1
+ {
+ [string] wchar_t * sesi1_cname;
+ [string] wchar_t * sesi1_username;
+ DWORD sesi1_num_opens;
+ DWORD sesi1_time;
+ DWORD sesi1_idle_time;
+ DWORD sesi1_user_flags;
+ } SESSION_INFO_1,
+ *PSESSION_INFO_1,
+ *LPSESSION_INFO_1;
+
+ typedef struct _SESSION_INFO_1_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSESSION_INFO_1 Buffer;
+ } SESSION_INFO_1_CONTAINER,
+ *PSESSION_INFO_1_CONTAINER,
+ *LPSESSION_INFO_1_CONTAINER;
+
+ typedef struct _SESSION_INFO_2
+ {
+ [string] wchar_t * sesi2_cname;
+ [string] wchar_t * sesi2_username;
+ DWORD sesi2_num_opens;
+ DWORD sesi2_time;
+ DWORD sesi2_idle_time;
+ DWORD sesi2_user_flags;
+ [string] wchar_t * sesi2_cltype_name;
+ } SESSION_INFO_2,
+ *PSESSION_INFO_2,
+ *LPSESSION_INFO_2;
+
+ typedef struct _SESSION_INFO_2_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSESSION_INFO_2 Buffer;
+ } SESSION_INFO_2_CONTAINER,
+ *PSESSION_INFO_2_CONTAINER,
+ *LPSESSION_INFO_2_CONTAINER;
+
+ typedef struct _SESSION_INFO_10
+ {
+ [string] wchar_t * sesi10_cname;
+ [string] wchar_t * sesi10_username;
+ DWORD sesi10_time;
+ DWORD sesi10_idle_time;
+ } SESSION_INFO_10,
+ *PSESSION_INFO_10,
+ *LPSESSION_INFO_10;
+
+ typedef struct _SESSION_INFO_10_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSESSION_INFO_10 Buffer;
+ } SESSION_INFO_10_CONTAINER,
+ *PSESSION_INFO_10_CONTAINER,
+ *LPSESSION_INFO_10_CONTAINER;
+
+ typedef struct _SESSION_INFO_502
+ {
+ [string] wchar_t * sesi502_cname;
+ [string] wchar_t * sesi502_username;
+ DWORD sesi502_num_opens;
+ DWORD sesi502_time;
+ DWORD sesi502_idle_time;
+ DWORD sesi502_user_flags;
+ [string] wchar_t * sesi502_cltype_name;
+ [string] wchar_t * sesi502_transport;
+ } SESSION_INFO_502,
+ *PSESSION_INFO_502,
+ *LPSESSION_INFO_502;
+
+ typedef struct _SESSION_INFO_502_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSESSION_INFO_502 Buffer;
+ } SESSION_INFO_502_CONTAINER,
+ *PSESSION_INFO_502_CONTAINER,
+ *LPSESSION_INFO_502_CONTAINER;
+
+ typedef [switch_type(DWORD)] union _SESSION_ENUM_UNION {
+[case(0)]
+ SESSION_INFO_0_CONTAINER* Level0;
+ [case(1)]
+ SESSION_INFO_1_CONTAINER* Level1;
+ [case(2)]
+ SESSION_INFO_2_CONTAINER* Level2;
+ [case(10)]
+ SESSION_INFO_10_CONTAINER* Level10;
+ [case(502)]
+ SESSION_INFO_502_CONTAINER* Level502;
+ } SESSION_ENUM_UNION;
+
+ typedef struct _SESSION_ENUM_STRUCT {
+ DWORD Level;
+ [switch_is(Level)] SESSION_ENUM_UNION SessionInfo;
+ } SESSION_ENUM_STRUCT,
+ *PSESSION_ENUM_STRUCT,
+ *LPSESSION_ENUM_STRUCT;
+
+ typedef struct _SHARE_INFO_502_I
+ {
+ [string] WCHAR * shi502_netname;
+ DWORD shi502_type;
+ [string] WCHAR * shi502_remark;
+ DWORD shi502_permissions;
+ DWORD shi502_max_uses;
+ DWORD shi502_current_uses;
+ [string] WCHAR * shi502_path;
+ [string] WCHAR * shi502_passwd;
+ DWORD shi502_reserved;
+ [size_is(shi502_reserved)] unsigned char
+ * shi502_security_descriptor;
+ } SHARE_INFO_502_I,
+ *PSHARE_INFO_502_I,
+ *LPSHARE_INFO_502_I;
+
+ typedef struct _SHARE_INFO_503_I
+ {
+ [string] WCHAR * shi503_netname;
+ DWORD shi503_type;
+ [string] WCHAR * shi503_remark;
+ DWORD shi503_permissions;
+ DWORD shi503_max_uses;
+ DWORD shi503_current_uses;
+ [string] WCHAR * shi503_path;
+ [string] WCHAR * shi503_passwd;
+ [string] WCHAR * shi503_servername;
+ DWORD shi503_reserved;
+ [size_is(shi503_reserved)] PUCHAR shi503_security_descriptor;
+ } SHARE_INFO_503_I,
+ *PSHARE_INFO_503_I,
+ *LPSHARE_INFO_503_I;
+
+ typedef struct _SHARE_INFO_503_CONTAINER
+ { DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSHARE_INFO_503_I Buffer;
+ } SHARE_INFO_503_CONTAINER,
+ *PSHARE_INFO_503_CONTAINER,
+ *LPSHARE_INFO_503_CONTAINER;
+
+ typedef struct _SHARE_INFO_1501_I
+ {
+ DWORD shi1501_reserved;
+ [size_is(shi1501_reserved)] unsigned char
+ * shi1501_security_descriptor;
+ } SHARE_INFO_1501_I,
+ *PSHARE_INFO_1501_I,
+ *LPSHARE_INFO_1501_I;
+
+ typedef struct _SHARE_INFO_0
+ {
+ [string] wchar_t * shi0_netname;
+ } SHARE_INFO_0,
+ *PSHARE_INFO_0,
+ *LPSHARE_INFO_0;
+
+ typedef struct _SHARE_INFO_0_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSHARE_INFO_0 Buffer;
+ } SHARE_INFO_0_CONTAINER;
+
+ typedef struct _SHARE_INFO_1
+ {
+ [string] wchar_t * shi1_netname;
+ DWORD shi1_type;
+ [string] wchar_t * shi1_remark;
+ } SHARE_INFO_1,
+ *PSHARE_INFO_1,
+ *LPSHARE_INFO_1;
+
+ typedef struct _SHARE_INFO_1_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSHARE_INFO_1 Buffer;
+ } SHARE_INFO_1_CONTAINER;
+
+ typedef struct _SHARE_INFO_2
+ {
+ [string] wchar_t * shi2_netname;
+ DWORD shi2_type;
+ [string] wchar_t * shi2_remark;
+ DWORD shi2_permissions;
+ DWORD shi2_max_uses;
+ DWORD shi2_current_uses;
+ [string] wchar_t * shi2_path;
+ [string] wchar_t * shi2_passwd;
+ } SHARE_INFO_2,
+ *PSHARE_INFO_2,
+ *LPSHARE_INFO_2;
+
+ typedef struct _SHARE_INFO_2_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSHARE_INFO_2 Buffer;
+ } SHARE_INFO_2_CONTAINER,
+ *PSHARE_INFO_2_CONTAINER,
+ *LPSHARE_INFO_2_CONTAINER;
+
+ typedef struct _SHARE_INFO_501
+ {
+ [string] wchar_t * shi501_netname;
+ DWORD shi501_type;
+ [string] wchar_t * shi501_remark;
+ DWORD shi501_flags;
+ } SHARE_INFO_501,
+ *PSHARE_INFO_501,
+ *LPSHARE_INFO_501;
+
+ typedef struct _SHARE_INFO_501_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSHARE_INFO_501 Buffer;
+ } SHARE_INFO_501_CONTAINER, *PSHARE_INFO_501_CONTAINER,
+ *LPSHARE_INFO_501_CONTAINER;
+
+ typedef struct _SHARE_INFO_502_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSHARE_INFO_502_I Buffer;
+ } SHARE_INFO_502_CONTAINER,
+ *PSHARE_INFO_502_CONTAINER,
+ *LPSHARE_INFO_502_CONTAINER;
+
+ typedef [switch_type(DWORD)] union _SHARE_ENUM_UNION {
+ [case(0)]
+ SHARE_INFO_0_CONTAINER* Level0;
+ [case(1)]
+ SHARE_INFO_1_CONTAINER* Level1;
+ [case(2)]
+ SHARE_INFO_2_CONTAINER* Level2;
+ [case(501)]
+ SHARE_INFO_501_CONTAINER* Level501;
+ [case(502)]
+ SHARE_INFO_502_CONTAINER* Level502;
+ [case(503)]
+ SHARE_INFO_503_CONTAINER* Level503;
+ } SHARE_ENUM_UNION;
+
+ typedef struct _SHARE_ENUM_STRUCT
+ {
+ DWORD Level;
+ [switch_is(Level)] SHARE_ENUM_UNION ShareInfo;
+ } SHARE_ENUM_STRUCT,
+ *PSHARE_ENUM_STRUCT,
+ *LPSHARE_ENUM_STRUCT;
+
+ typedef struct _SHARE_INFO_1004
+ {
+ [string] wchar_t * shi1004_remark;
+ } SHARE_INFO_1004,
+ *PSHARE_INFO_1004,
+ *LPSHARE_INFO_1004;
+
+ typedef struct _SHARE_INFO_1006
+ {
+ DWORD shi1006_max_uses;
+ } SHARE_INFO_1006,
+ *PSHARE_INFO_1006,
+ *LPSHARE_INFO_1006;
+
+ typedef struct _SHARE_INFO_1005
+ {
+ DWORD shi1005_flags;
+ } SHARE_INFO_1005,
+ *PSHARE_INFO_1005,
+ *LPSHARE_INFO_1005;
+
+//JMP: order differs in documentation
+ typedef [switch_type(unsigned long)] union _SHARE_INFO
+// for Get & Set info
+ {
+ [case(0)]
+ LPSHARE_INFO_0 ShareInfo0;
+ [case(1)]
+ LPSHARE_INFO_1 ShareInfo1;
+ [case(2)]
+ LPSHARE_INFO_2 ShareInfo2;
+ [case(502)]
+ LPSHARE_INFO_502_I ShareInfo502;
+ [case(1004)]
+ LPSHARE_INFO_1004 ShareInfo1004;
+ [case(1006)]
+ LPSHARE_INFO_1006 ShareInfo1006;
+ [case(1501)]
+ LPSHARE_INFO_1501_I ShareInfo1501;
+ [default]
+ ;
+ [case(1005)]
+ LPSHARE_INFO_1005 ShareInfo1005;
+ [case(501)]
+ LPSHARE_INFO_501 ShareInfo501;
+ [case(503)]
+ LPSHARE_INFO_503_I ShareInfo503;
+ } SHARE_INFO,
+ *PSHARE_INFO,
+ *LPSHARE_INFO;
+
+ typedef struct _SERVER_INFO_100
+ {
+ DWORD sv100_platform_id;
+ [string] wchar_t * sv100_name;
+ } SERVER_INFO_100,
+ *PSERVER_INFO_100,
+ *LPSERVER_INFO_100;
+
+ typedef struct _SERVER_INFO_101
+ {
+ DWORD sv101_platform_id;
+ [string] wchar_t * sv101_name;
+ DWORD sv101_version_major;
+ DWORD sv101_version_minor;
+ DWORD sv101_type;
+ [string] wchar_t * sv101_comment;
+ } SERVER_INFO_101,
+ *PSERVER_INFO_101,
+ *LPSERVER_INFO_101;
+
+ typedef struct _SERVER_INFO_102
+ {
+ DWORD sv102_platform_id;
+ [string] wchar_t * sv102_name;
+ DWORD sv102_version_major;
+ DWORD sv102_version_minor;
+ DWORD sv102_type;
+ [string] wchar_t * sv102_comment;
+ DWORD sv102_users;
+ long sv102_disc;
+ int sv102_hidden;
+ DWORD sv102_announce;
+ DWORD sv102_anndelta;
+ DWORD sv102_licenses;
+ [string] wchar_t * sv102_userpath;
+ } SERVER_INFO_102,
+ *PSERVER_INFO_102,
+ *LPSERVER_INFO_102;
+
+ typedef struct _SERVER_INFO_103
+ {
+ DWORD sv103_platform_id;
+ [string] wchar_t* sv103_name;
+ DWORD sv103_version_major;
+ DWORD sv103_version_minor;
+ DWORD sv103_type;
+ [string] wchar_t* sv103_comment;
+ DWORD sv103_users;
+ LONG sv103_disc;
+ BOOL sv103_hidden;
+ DWORD sv103_announce;
+ DWORD sv103_anndelta;
+ DWORD sv103_licenses;
+ [string] wchar_t* sv103_userpath;
+ DWORD sv103_capabilities;
+ } SERVER_INFO_103,
+ *PSERVER_INFO_103,
+ *LPSERVER_INFO_103;
+
+ typedef struct _SERVER_INFO_502
+ {
+ DWORD sv502_sessopens;
+ DWORD sv502_sessvcs;
+ DWORD sv502_opensearch;
+ DWORD sv502_sizreqbuf;
+ DWORD sv502_initworkitems;
+ DWORD sv502_maxworkitems;
+ DWORD sv502_rawworkitems;
+ DWORD sv502_irpstacksize;
+ DWORD sv502_maxrawbuflen;
+ DWORD sv502_sessusers;
+ DWORD sv502_sessconns;
+ DWORD sv502_maxpagedmemoryusage;
+ DWORD sv502_maxnonpagedmemoryusage;
+ int sv502_enablesoftcompat;
+ int sv502_enableforcedlogoff;
+ int sv502_timesource;
+ int sv502_acceptdownlevelapis;
+ int sv502_lmannounce;
+ } SERVER_INFO_502,
+ *PSERVER_INFO_502,
+ *LPSERVER_INFO_502;
+
+ typedef struct _SERVER_INFO_503
+ {
+ DWORD sv503_sessopens;
+ DWORD sv503_sessvcs;
+ DWORD sv503_opensearch;
+ DWORD sv503_sizreqbuf;
+ DWORD sv503_initworkitems;
+ DWORD sv503_maxworkitems;
+ DWORD sv503_rawworkitems;
+ DWORD sv503_irpstacksize;
+ DWORD sv503_maxrawbuflen;
+ DWORD sv503_sessusers;
+ DWORD sv503_sessconns;
+ DWORD sv503_maxpagedmemoryusage;
+ DWORD sv503_maxnonpagedmemoryusage;
+ int sv503_enablesoftcompat;
+ int sv503_enableforcedlogoff;
+ int sv503_timesource;
+ int sv503_acceptdownlevelapis;
+ int sv503_lmannounce;
+ [string] wchar_t * sv503_domain;
+ DWORD sv503_maxcopyreadlen;
+ DWORD sv503_maxcopywritelen;
+ DWORD sv503_minkeepsearch;
+ DWORD sv503_maxkeepsearch;
+ DWORD sv503_minkeepcomplsearch;
+ DWORD sv503_maxkeepcomplsearch;
+ DWORD sv503_threadcountadd;
+ DWORD sv503_numblockthreads;
+ DWORD sv503_scavtimeout;
+ DWORD sv503_minrcvqueue;
+ DWORD sv503_minfreeworkitems;
+ DWORD sv503_xactmemsize;
+ DWORD sv503_threadpriority;
+ DWORD sv503_maxmpxct;
+ DWORD sv503_oplockbreakwait;
+ DWORD sv503_oplockbreakresponsewait;
+ int sv503_enableoplocks;
+ int sv503_enableoplockforceclose;
+ int sv503_enablefcbopens;
+ int sv503_enableraw;
+ int sv503_enablesharednetdrives;
+ DWORD sv503_minfreeconnections;
+ DWORD sv503_maxfreeconnections;
+ } SERVER_INFO_503,
+ *PSERVER_INFO_503,
+ *LPSERVER_INFO_503;
+
+ typedef struct _SERVER_INFO_599
+ {
+ DWORD sv599_sessopens;
+ DWORD sv599_sessvcs;
+ DWORD sv599_opensearch;
+ DWORD sv599_sizreqbuf;
+ DWORD sv599_initworkitems;
+ DWORD sv599_maxworkitems;
+ DWORD sv599_rawworkitems;
+ DWORD sv599_irpstacksize;
+ DWORD sv599_maxrawbuflen;
+ DWORD sv599_sessusers;
+ DWORD sv599_sessconns;
+ DWORD sv599_maxpagedmemoryusage;
+ DWORD sv599_maxnonpagedmemoryusage;
+ int sv599_enablesoftcompat;
+ int sv599_enableforcedlogoff;
+ int sv599_timesource;
+ int sv599_acceptdownlevelapis;
+ int sv599_lmannounce;
+ [string] wchar_t * sv599_domain;
+ DWORD sv599_maxcopyreadlen;
+ DWORD sv599_maxcopywritelen;
+ DWORD sv599_minkeepsearch;
+ DWORD sv599_maxkeepsearch;
+ DWORD sv599_minkeepcomplsearch;
+ DWORD sv599_maxkeepcomplsearch;
+ DWORD sv599_threadcountadd;
+ DWORD sv599_numblockthreads;
+ DWORD sv599_scavtimeout;
+ DWORD sv599_minrcvqueue;
+ DWORD sv599_minfreeworkitems;
+ DWORD sv599_xactmemsize;
+ DWORD sv599_threadpriority;
+ DWORD sv599_maxmpxct;
+ DWORD sv599_oplockbreakwait;
+ DWORD sv599_oplockbreakresponsewait;
+ int sv599_enableoplocks;
+ int sv599_enableoplockforceclose;
+ int sv599_enablefcbopens;
+ int sv599_enableraw;
+ int sv599_enablesharednetdrives;
+ DWORD sv599_minfreeconnections;
+ DWORD sv599_maxfreeconnections;
+ DWORD sv599_initsesstable;
+ DWORD sv599_initconntable;
+ DWORD sv599_initfiletable;
+ DWORD sv599_initsearchtable;
+ DWORD sv599_alertschedule;
+ DWORD sv599_errorthreshold;
+ DWORD sv599_networkerrorthreshold;
+ DWORD sv599_diskspacethreshold;
+ DWORD sv599_reserved;
+ DWORD sv599_maxlinkdelay;
+ DWORD sv599_minlinkthroughput;
+ DWORD sv599_linkinfovalidtime;
+ DWORD sv599_scavqosinfoupdatetime;
+ DWORD sv599_maxworkitemidletime;
+ } SERVER_INFO_599,
+ *PSERVER_INFO_599,
+ *LPSERVER_INFO_599;
+
+ typedef struct _SERVER_INFO_1005
+ {
+ [string] wchar_t * sv1005_comment;
+ } SERVER_INFO_1005,
+ *PSERVER_INFO_1005,
+ *LPSERVER_INFO_1005;
+
+ typedef struct _SERVER_INFO_1107
+ {
+ DWORD sv1107_users;
+ } SERVER_INFO_1107,
+ *PSERVER_INFO_1107,
+ *LPSERVER_INFO_1107;
+
+ typedef struct _SERVER_INFO_1010
+ {
+ long sv1010_disc;
+ } SERVER_INFO_1010,
+ *PSERVER_INFO_1010,
+ *LPSERVER_INFO_1010;
+
+ typedef struct _SERVER_INFO_1016
+ {
+ int sv1016_hidden;
+ } SERVER_INFO_1016,
+ *PSERVER_INFO_1016,
+ *LPSERVER_INFO_1016;
+
+ typedef struct _SERVER_INFO_1017
+ {
+ DWORD sv1017_announce;
+ } SERVER_INFO_1017,
+ *PSERVER_INFO_1017,
+ *LPSERVER_INFO_1017;
+
+ typedef struct _SERVER_INFO_1018
+ {
+ DWORD sv1018_anndelta;
+ } SERVER_INFO_1018,
+ *PSERVER_INFO_1018,
+ *LPSERVER_INFO_1018;
+
+ typedef struct _SERVER_INFO_1501
+ {
+ DWORD sv1501_sessopens;
+ } SERVER_INFO_1501,
+ *PSERVER_INFO_1501,
+ *LPSERVER_INFO_1501;
+
+ typedef struct _SERVER_INFO_1502
+ {
+ DWORD sv1502_sessvcs;
+ } SERVER_INFO_1502,
+ *PSERVER_INFO_1502,
+ *LPSERVER_INFO_1502;
+
+ typedef struct _SERVER_INFO_1503
+ {
+ DWORD sv1503_opensearch;
+ } SERVER_INFO_1503, *PSERVER_INFO_1503, *LPSERVER_INFO_1503;
+
+ typedef struct _SERVER_INFO_1506
+ {
+ DWORD sv1506_maxworkitems;
+ } SERVER_INFO_1506, *PSERVER_INFO_1506, *LPSERVER_INFO_1506;
+
+ typedef struct _SERVER_INFO_1510
+ {
+ DWORD sv1510_sessusers;
+ } SERVER_INFO_1510, *PSERVER_INFO_1510, *LPSERVER_INFO_1510;
+
+ typedef struct _SERVER_INFO_1511
+ {
+ DWORD sv1511_sessconns;
+ } SERVER_INFO_1511, *PSERVER_INFO_1511, *LPSERVER_INFO_1511;
+
+ typedef struct _SERVER_INFO_1512
+ {
+ DWORD sv1512_maxnonpagedmemoryusage;
+ } SERVER_INFO_1512, *PSERVER_INFO_1512, *LPSERVER_INFO_1512;
+
+ typedef struct _SERVER_INFO_1513
+ {
+ DWORD sv1513_maxpagedmemoryusage;
+ } SERVER_INFO_1513, *PSERVER_INFO_1513, *LPSERVER_INFO_1513;
+
+ typedef struct _SERVER_INFO_1514
+ {
+ int sv1514_enablesoftcompat;
+ } SERVER_INFO_1514, *PSERVER_INFO_1514, *LPSERVER_INFO_1514;
+
+ typedef struct _SERVER_INFO_1515
+ {
+ int sv1515_enableforcedlogoff;
+ } SERVER_INFO_1515, *PSERVER_INFO_1515, *LPSERVER_INFO_1515;
+
+ typedef struct _SERVER_INFO_1516
+ {
+ int sv1516_timesource;
+ } SERVER_INFO_1516, *PSERVER_INFO_1516, *LPSERVER_INFO_1516;
+
+ typedef struct _SERVER_INFO_1518
+ {
+ int sv1518_lmannounce;
+ } SERVER_INFO_1518, *PSERVER_INFO_1518, *LPSERVER_INFO_1518;
+
+ typedef struct _SERVER_INFO_1523
+ {
+ DWORD sv1523_maxkeepsearch;
+ } SERVER_INFO_1523, *PSERVER_INFO_1523, *LPSERVER_INFO_1523;
+
+ typedef struct _SERVER_INFO_1528
+ {
+ DWORD sv1528_scavtimeout;
+ } SERVER_INFO_1528, *PSERVER_INFO_1528, *LPSERVER_INFO_1528;
+
+ typedef struct _SERVER_INFO_1529
+ {
+ DWORD sv1529_minrcvqueue;
+ } SERVER_INFO_1529, *PSERVER_INFO_1529, *LPSERVER_INFO_1529;
+
+ typedef struct _SERVER_INFO_1530
+ {
+ DWORD sv1530_minfreeworkitems;
+ } SERVER_INFO_1530, *PSERVER_INFO_1530, *LPSERVER_INFO_1530;
+
+ typedef struct _SERVER_INFO_1533
+ {
+ DWORD sv1533_maxmpxct;
+ } SERVER_INFO_1533, *PSERVER_INFO_1533, *LPSERVER_INFO_1533;
+
+ typedef struct _SERVER_INFO_1534
+ {
+ DWORD sv1534_oplockbreakwait;
+ } SERVER_INFO_1534, *PSERVER_INFO_1534, *LPSERVER_INFO_1534;
+
+ typedef struct _SERVER_INFO_1535
+ {
+ DWORD sv1535_oplockbreakresponsewait;
+ } SERVER_INFO_1535, *PSERVER_INFO_1535, *LPSERVER_INFO_1535;
+
+ typedef struct _SERVER_INFO_1536
+ {
+ int sv1536_enableoplocks;
+ } SERVER_INFO_1536, *PSERVER_INFO_1536, *LPSERVER_INFO_1536;
+
+ typedef struct _SERVER_INFO_1538
+ {
+ int sv1538_enablefcbopens;
+ } SERVER_INFO_1538, *PSERVER_INFO_1538, *LPSERVER_INFO_1538;
+
+ typedef struct _SERVER_INFO_1539
+ {
+ int sv1539_enableraw;
+ } SERVER_INFO_1539, *PSERVER_INFO_1539, *LPSERVER_INFO_1539;
+
+ typedef struct _SERVER_INFO_1540
+ {
+ int sv1540_enablesharednetdrives;
+ } SERVER_INFO_1540, *PSERVER_INFO_1540, *LPSERVER_INFO_1540;
+
+ typedef struct _SERVER_INFO_1541
+ {
+ int sv1541_minfreeconnections;
+ } SERVER_INFO_1541, *PSERVER_INFO_1541, *LPSERVER_INFO_1541;
+
+ typedef struct _SERVER_INFO_1542
+ {
+ int sv1542_maxfreeconnections;
+ } SERVER_INFO_1542, *PSERVER_INFO_1542, *LPSERVER_INFO_1542;
+
+ typedef struct _SERVER_INFO_1543
+ {
+ DWORD sv1543_initsesstable;
+ } SERVER_INFO_1543, *PSERVER_INFO_1543, *LPSERVER_INFO_1543;
+
+ typedef struct _SERVER_INFO_1544
+ {
+ DWORD sv1544_initconntable;
+ } SERVER_INFO_1544, *PSERVER_INFO_1544, *LPSERVER_INFO_1544;
+
+ typedef struct _SERVER_INFO_1545
+ {
+ DWORD sv1545_initfiletable;
+ } SERVER_INFO_1545, *PSERVER_INFO_1545, *LPSERVER_INFO_1545;
+
+ typedef struct _SERVER_INFO_1546
+ {
+ DWORD sv1546_initsearchtable;
+ } SERVER_INFO_1546, *PSERVER_INFO_1546, *LPSERVER_INFO_1546;
+
+ typedef struct _SERVER_INFO_1547
+ {
+ DWORD sv1547_alertschedule;
+ } SERVER_INFO_1547, *PSERVER_INFO_1547, *LPSERVER_INFO_1547;
+
+ typedef struct _SERVER_INFO_1548
+ {
+ DWORD sv1548_errorthreshold;
+ } SERVER_INFO_1548, *PSERVER_INFO_1548, *LPSERVER_INFO_1548;
+
+ typedef struct _SERVER_INFO_1549
+ {
+ DWORD sv1549_networkerrorthreshold;
+ } SERVER_INFO_1549, *PSERVER_INFO_1549, *LPSERVER_INFO_1549;
+
+ typedef struct _SERVER_INFO_1550
+ {
+ DWORD sv1550_diskspacethreshold;
+ } SERVER_INFO_1550, *PSERVER_INFO_1550, *LPSERVER_INFO_1550;
+
+ typedef struct _SERVER_INFO_1552
+ {
+ DWORD sv1552_maxlinkdelay;
+ } SERVER_INFO_1552, *PSERVER_INFO_1552, *LPSERVER_INFO_1552;
+
+ typedef struct _SERVER_INFO_1553
+ {
+ DWORD sv1553_minlinkthroughput;
+ } SERVER_INFO_1553, *PSERVER_INFO_1553, *LPSERVER_INFO_1553;
+
+ typedef struct _SERVER_INFO_1554
+ {
+ DWORD sv1554_linkinfovalidtime;
+ } SERVER_INFO_1554, *PSERVER_INFO_1554, *LPSERVER_INFO_1554;
+
+ typedef struct _SERVER_INFO_1555
+ {
+ DWORD sv1555_scavqosinfoupdatetime;
+ } SERVER_INFO_1555, *PSERVER_INFO_1555, *LPSERVER_INFO_1555;
+
+ typedef struct _SERVER_INFO_1556
+ {
+ DWORD sv1556_maxworkitemidletime;
+ } SERVER_INFO_1556, *PSERVER_INFO_1556, *LPSERVER_INFO_1556;
+
+ typedef [switch_type(unsigned long)] union _SERVER_INFO
+ {
+ [case(100)]
+ LPSERVER_INFO_100 ServerInfo100;
+ [case(101)]
+ LPSERVER_INFO_101 ServerInfo101;
+ [case(102)]
+ LPSERVER_INFO_102 ServerInfo102;
+ [case(103)]
+ LPSERVER_INFO_103 ServerInfo103;
+ [case(502)]
+ LPSERVER_INFO_502 ServerInfo502;
+ [case(503)]
+ LPSERVER_INFO_503 ServerInfo503;
+ [case(599)]
+ LPSERVER_INFO_599 ServerInfo599;
+ [case(1005)]
+ LPSERVER_INFO_1005 ServerInfo1005;
+ [case(1107)]
+ LPSERVER_INFO_1107 ServerInfo1107;
+ [case(1010)]
+ LPSERVER_INFO_1010 ServerInfo1010;
+ [case(1016)]
+ LPSERVER_INFO_1016 ServerInfo1016;
+ [case(1017)]
+ LPSERVER_INFO_1017 ServerInfo1017;
+ [case(1018)]
+ LPSERVER_INFO_1018 ServerInfo1018;
+ [case(1501)]
+ LPSERVER_INFO_1501 ServerInfo1501;
+ [case(1502)]
+ LPSERVER_INFO_1502 ServerInfo1502;
+ [case(1503)]
+ LPSERVER_INFO_1503 ServerInfo1503;
+ [case(1506)]
+ LPSERVER_INFO_1506 ServerInfo1506;
+ [case(1510)]
+ LPSERVER_INFO_1510 ServerInfo1510;
+ [case(1511)]
+ LPSERVER_INFO_1511 ServerInfo1511;
+ [case(1512)]
+ LPSERVER_INFO_1512 ServerInfo1512;
+ [case(1513)]
+ LPSERVER_INFO_1513 ServerInfo1513;
+ [case(1514)]
+ LPSERVER_INFO_1514 ServerInfo1514;
+ [case(1515)]
+ LPSERVER_INFO_1515 ServerInfo1515;
+ [case(1516)]
+ LPSERVER_INFO_1516 ServerInfo1516;
+ [case(1518)]
+ LPSERVER_INFO_1518 ServerInfo1518;
+ [case(1523)]
+ LPSERVER_INFO_1523 ServerInfo1523;
+ [case(1528)]
+ LPSERVER_INFO_1528 ServerInfo1528;
+ [case(1529)]
+ LPSERVER_INFO_1529 ServerInfo1529;
+ [case(1530)]
+ LPSERVER_INFO_1530 ServerInfo1530;
+ [case(1533)]
+ LPSERVER_INFO_1533 ServerInfo1533;
+ [case(1534)]
+ LPSERVER_INFO_1534 ServerInfo1534;
+ [case(1535)]
+ LPSERVER_INFO_1535 ServerInfo1535;
+ [case(1536)]
+ LPSERVER_INFO_1536 ServerInfo1536;
+ [case(1538)]
+ LPSERVER_INFO_1538 ServerInfo1538;
+ [case(1539)]
+ LPSERVER_INFO_1539 ServerInfo1539;
+ [case(1540)]
+ LPSERVER_INFO_1540 ServerInfo1540;
+ [case(1541)]
+ LPSERVER_INFO_1541 ServerInfo1541;
+ [case(1542)]
+ LPSERVER_INFO_1542 ServerInfo1542;
+ [case(1543)]
+ LPSERVER_INFO_1543 ServerInfo1543;
+ [case(1544)]
+ LPSERVER_INFO_1544 ServerInfo1544;
+ [case(1545)]
+ LPSERVER_INFO_1545 ServerInfo1545;
+ [case(1546)]
+ LPSERVER_INFO_1546 ServerInfo1546;
+ [case(1547)]
+ LPSERVER_INFO_1547 ServerInfo1547;
+ [case(1548)]
+ LPSERVER_INFO_1548 ServerInfo1548;
+ [case(1549)]
+ LPSERVER_INFO_1549 ServerInfo1549;
+ [case(1550)]
+ LPSERVER_INFO_1550 ServerInfo1550;
+ [case(1552)]
+ LPSERVER_INFO_1552 ServerInfo1552;
+ [case(1553)]
+ LPSERVER_INFO_1553 ServerInfo1553;
+ [case(1554)]
+ LPSERVER_INFO_1554 ServerInfo1554;
+ [case(1555)]
+ LPSERVER_INFO_1555 ServerInfo1555;
+ [case(1556)]
+ LPSERVER_INFO_1556 ServerInfo1556;
+ } SERVER_INFO, *PSERVER_INFO, *LPSERVER_INFO;
+
+ typedef struct _DISK_INFO
+ {
+ [string] WCHAR Disk[3];
+ } DISK_INFO, *PDISK_INFO, *LPDISK_INFO;
+
+ typedef struct _DISK_ENUM_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead), length_is(EntriesRead)] LPDISK_INFO
+ Buffer;
+ } DISK_ENUM_CONTAINER;
+
+ typedef struct _SERVER_TRANSPORT_INFO_0
+ {
+ DWORD svti0_numberofvcs;
+ [string] wchar_t * svti0_transportname;
+ [size_is(svti0_transportaddresslength)] unsigned char
+ * svti0_transportaddress;
+ DWORD svti0_transportaddresslength;
+ [string] wchar_t * svti0_networkaddress;
+ } SERVER_TRANSPORT_INFO_0, *PSERVER_TRANSPORT_INFO_0,
+ *LPSERVER_TRANSPORT_INFO_0;
+
+ typedef struct _SERVER_XPORT_INFO_0_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSERVER_TRANSPORT_INFO_0 Buffer;
+ } SERVER_XPORT_INFO_0_CONTAINER, *PSERVER_XPORT_INFO_0_CONTAINER;
+
+ typedef struct _SERVER_TRANSPORT_INFO_1
+ {
+ DWORD svti1_numberofvcs;
+ [string] wchar_t * svti1_transportname;
+ [size_is(svti1_transportaddresslength)] unsigned char
+ * svti1_transportaddress;
+ DWORD svti1_transportaddresslength;
+ [string] wchar_t * svti1_networkaddress;
+ [string] wchar_t * svti1_domain;
+ } SERVER_TRANSPORT_INFO_1, *PSERVER_TRANSPORT_INFO_1,
+ *LPSERVER_TRANSPORT_INFO_1;
+
+ typedef struct _SERVER_XPORT_INFO_1_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSERVER_TRANSPORT_INFO_1 Buffer;
+ } SERVER_XPORT_INFO_1_CONTAINER, *PSERVER_XPORT_INFO_1_CONTAINER;
+
+ typedef struct _SERVER_TRANSPORT_INFO_2
+ {
+ DWORD svti2_numberofvcs;
+ [string] wchar_t * svti2_transportname;
+ [size_is(svti2_transportaddresslength)] unsigned char
+ * svti2_transportaddress;
+ DWORD svti2_transportaddresslength;
+ [string] wchar_t * svti2_networkaddress;
+ [string] wchar_t * svti2_domain;
+ unsigned long svti2_flags;
+ } SERVER_TRANSPORT_INFO_2, *PSERVER_TRANSPORT_INFO_2,
+ *LPSERVER_TRANSPORT_INFO_2;
+
+ typedef struct _SERVER_XPORT_INFO_2_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSERVER_TRANSPORT_INFO_2 Buffer;
+ } SERVER_XPORT_INFO_2_CONTAINER, *PSERVER_XPORT_INFO_2_CONTAINER;
+
+ typedef struct _SERVER_TRANSPORT_INFO_3
+ {
+ DWORD svti3_numberofvcs;
+ [string] wchar_t * svti3_transportname;
+ [size_is(svti3_transportaddresslength)] unsigned char
+ * svti3_transportaddress;
+ DWORD svti3_transportaddresslength;
+ [string] wchar_t * svti3_networkaddress;
+ [string] wchar_t * svti3_domain;
+ unsigned long svti3_flags;
+ DWORD svti3_passwordlength;
+ unsigned char svti3_password[ 256 ];
+ } SERVER_TRANSPORT_INFO_3, *PSERVER_TRANSPORT_INFO_3,
+ *LPSERVER_TRANSPORT_INFO_3;
+
+ typedef struct _SERVER_XPORT_INFO_3_CONTAINER
+ {
+ DWORD EntriesRead;
+ [size_is(EntriesRead)] LPSERVER_TRANSPORT_INFO_3 Buffer;
+ } SERVER_XPORT_INFO_3_CONTAINER, *PSERVER_XPORT_INFO_3_CONTAINER;
+
+ typedef [switch_type(unsigned long)] union _TRANSPORT_INFO
+ {
+ [case(0)]
+ SERVER_TRANSPORT_INFO_0 Transport0;
+ [case(1)]
+ SERVER_TRANSPORT_INFO_1 Transport1;
+ [case(2)]
+ SERVER_TRANSPORT_INFO_2 Transport2;
+ [case(3)]
+ SERVER_TRANSPORT_INFO_3 Transport3;
+ } TRANSPORT_INFO, *PTRANSPORT_INFO, *LPTRANSPORT_INFO;
+
+ typedef [switch_type(DWORD)] union _SERVER_XPORT_ENUM_UNION {
+ [case(0)]
+ PSERVER_XPORT_INFO_0_CONTAINER Level0;
+ [case(1)]
+ PSERVER_XPORT_INFO_1_CONTAINER Level1;
+ [case(2)]
+ PSERVER_XPORT_INFO_2_CONTAINER Level2;
+ [case(3)]
+ PSERVER_XPORT_INFO_3_CONTAINER Level3;
+ } SERVER_XPORT_ENUM_UNION;
+
+ typedef struct _SERVER_XPORT_ENUM_STRUCT
+ {
+ DWORD Level;
+ [switch_is(Level)] SERVER_XPORT_ENUM_UNION XportInfo;
+
+ } SERVER_XPORT_ENUM_STRUCT, *PSERVER_XPORT_ENUM_STRUCT,
+ *LPSERVER_XPORT_ENUM_STRUCT;
+
+ typedef [context_handle] void *SHARE_DEL_HANDLE;
+ typedef SHARE_DEL_HANDLE *PSHARE_DEL_HANDLE;
+
+ typedef struct _ADT_SECURITY_DESCRIPTOR
+ {
+ DWORD Length;
+ [size_is(Length)] unsigned char * Buffer;
+ } ADT_SECURITY_DESCRIPTOR, *PADT_SECURITY_DESCRIPTOR;
+
+ typedef struct _STAT_SERVER_0
+ {
+ DWORD sts0_start;
+ DWORD sts0_fopens;
+ DWORD sts0_devopens;
+ DWORD sts0_jobsqueued;
+ DWORD sts0_sopens;
+ DWORD sts0_stimedout;
+ DWORD sts0_serrorout;
+ DWORD sts0_pwerrors;
+ DWORD sts0_permerrors;
+ DWORD sts0_syserrors;
+ DWORD sts0_bytessent_low;
+ DWORD sts0_bytessent_high;
+ DWORD sts0_bytesrcvd_low;
+ DWORD sts0_bytesrcvd_high;
+ DWORD sts0_avresponse;
+ DWORD sts0_reqbufneed;
+ DWORD sts0_bigbufneed;
+ } STAT_SERVER_0, *PSTAT_SERVER_0, *LPSTAT_SERVER_0;
+
+ typedef struct _TIME_OF_DAY_INFO
+ {
+ DWORD tod_elapsedt;
+ DWORD tod_msecs;
+ DWORD tod_hours;
+ DWORD tod_mins;
+ DWORD tod_secs;
+ DWORD tod_hunds;
+ long tod_timezone;
+ DWORD tod_tinterval;
+ DWORD tod_day;
+ DWORD tod_month;
+ DWORD tod_year;
+ DWORD tod_weekday;
+ } TIME_OF_DAY_INFO, *PTIME_OF_DAY_INFO, *LPTIME_OF_DAY_INFO;
+
+ typedef struct _NET_DFS_ENTRY_ID
+ {
+ GUID Uid;
+ [string] WCHAR * Prefix;
+ } NET_DFS_ENTRY_ID, *LPNET_DFS_ENTRY_ID;
+
+ typedef struct _NET_DFS_ENTRY_ID_CONTAINER
+ {
+ unsigned long Count;
+ [size_is(Count)] LPNET_DFS_ENTRY_ID Buffer;
+ } NET_DFS_ENTRY_ID_CONTAINER, *LPNET_DFS_ENTRY_ID_CONTAINER;
+
+ typedef struct _DFS_SITENAME_INFO
+ {
+ unsigned long SiteFlags;
+ [string,unique] WCHAR * SiteName;
+ } DFS_SITENAME_INFO, *PDFS_SITENAME_INFO, *LPDFS_SITENAME_INFO;
+
+ typedef struct _DFS_SITELIST_INFO
+ {
+ unsigned long cSites;
+ [size_is(cSites)] DFS_SITENAME_INFO Site[];
+ } DFS_SITELIST_INFO, *PDFS_SITELIST_INFO, *LPDFS_SITELIST_INFO;
+
+typedef struct _SERVER_ALIAS_INFO_0 {
+LMSTR srvai0_alias;
+LMSTR srvai0_target;
+BOOLEAN srvai0_default;
+ULONG srvai0_reserved;
+}SERVER_ALIAS_INFO_0, *PSERVER_ALIAS_INFO_0, *LPSERVER_ALIAS_INFO_0;
+
+typedef struct _SERVER_ALIAS_INFO_0_CONTAINER {
+DWORD EntriesRead;
+[size_is(EntriesRead)] LPSERVER_ALIAS_INFO_0 Buffer;
+} SERVER_ALIAS_INFO_0_CONTAINER;
+
+typedef struct _SERVER_ALIAS_ENUM_STRUCT {
+DWORD Level;
+[switch_is(Level)] union SERVER_ALIAS_ENUM_UNION {
+[case(0)]
+SERVER_ALIAS_INFO_0_CONTAINER *Level0;
+} ServerAliasInfo;
+}SERVER_ALIAS_ENUM_STRUCT, *PSERVER_ALIAS_ENUM_STRUCT,
+ *LPSERVER_ALIAS_ENUM_STRUCT;
+
+typedef [switch_type(unsigned long)] union _SERVER_ALIAS_INFO
+ { // for Get & Set Info
+[case(0)]
+LPSERVER_ALIAS_INFO_0 ServerAliasInfo0;
+} SERVER_ALIAS_INFO, *PSERVER_ALIAS_INFO, *LPSERVER_ALIAS_INFO;
+
+// This method not used on the wire
+ void Opnum0NotUsedOnWire(void);
+
+// This method not used on the wire
+ void Opnum1NotUsedOnWire(void);
+
+// This method not used on the wire
+ void Opnum2NotUsedOnWire(void);
+
+// This method not used on the wire
+ void Opnum3NotUsedOnWire(void);
+
+// This method not used on the wire
+ void Opnum4NotUsedOnWire(void);
+
+// This method not used on the wire
+ void Opnum5NotUsedOnWire(void);
+
+// This method not used on the wire
+ void Opnum6NotUsedOnWire(void);
+
+// This method not used on the wire
+ void Opnum7NotUsedOnWire(void);
+
+ NET_API_STATUS
+ NetrConnectionEnum (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string,unique] WCHAR * Qualifier,
+ [in,out] LPCONNECT_ENUM_STRUCT InfoStruct,
+ [in] DWORD PreferedMaximumLength,
+ [out] DWORD * TotalEntries,
+ [in,out,unique] DWORD * ResumeHandle
+ );
+
+ NET_API_STATUS
+ NetrFileEnum (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string,unique] WCHAR * BasePath,
+ [in,string,unique] WCHAR * UserName,
+ [in,out] PFILE_ENUM_STRUCT InfoStruct,
+ [in] DWORD PreferedMaximumLength,
+ [out] DWORD * TotalEntries,
+ [in,out,unique] DWORD * ResumeHandle
+ );
+
+ NET_API_STATUS
+ NetrFileGetInfo (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD FileId,
+ [in] DWORD Level,
+ [out, switch_is(Level)] LPFILE_INFO InfoStruct
+ );
+
+ NET_API_STATUS
+ NetrFileClose (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD FileId
+ );
+
+ NET_API_STATUS
+ NetrSessionEnum (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string,unique] WCHAR * ClientName,
+ [in,string,unique] WCHAR * UserName,
+ [in,out] PSESSION_ENUM_STRUCT InfoStruct,
+ [in] DWORD PreferedMaximumLength,
+ [out] DWORD * TotalEntries,
+ [in,out,unique] DWORD * ResumeHandle
+ );
+
+ NET_API_STATUS
+ NetrSessionDel (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string,unique] WCHAR * ClientName,
+ [in,string,unique] WCHAR * UserName
+ );
+
+ NET_API_STATUS
+ NetrShareAdd (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in, switch_is(Level)] LPSHARE_INFO InfoStruct,
+ [in,out,unique] DWORD * ParmErr
+ );
+
+ NET_API_STATUS
+ NetrShareEnum (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,out] LPSHARE_ENUM_STRUCT InfoStruct,
+ [in] DWORD PreferedMaximumLength,
+ [out] DWORD * TotalEntries,
+ [in,out,unique] DWORD * ResumeHandle
+ );
+
+ NET_API_STATUS
+ NetrShareGetInfo (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * NetName,
+ [in] DWORD Level,
+ [out, switch_is(Level)] LPSHARE_INFO InfoStruct
+ );
+
+ NET_API_STATUS
+ NetrShareSetInfo (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * NetName,
+ [in] DWORD Level,
+ [in, switch_is(Level)] LPSHARE_INFO ShareInfo,
+ [in,out,unique] DWORD * ParmErr
+ );
+
+ NET_API_STATUS
+ NetrShareDel (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * NetName,
+ [in] DWORD Reserved
+ );
+
+ NET_API_STATUS
+ NetrShareDelSticky (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * NetName,
+ [in] DWORD Reserved
+ );
+
+ NET_API_STATUS
+ NetrShareCheck (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * Device,
+ [out] DWORD * Type
+ );
+
+ NET_API_STATUS
+ NetrServerGetInfo (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [out, switch_is(Level)] LPSERVER_INFO InfoStruct
+ );
+
+ NET_API_STATUS
+ NetrServerSetInfo (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in, switch_is(Level)] LPSERVER_INFO ServerInfo,
+ [in,out,unique] DWORD * ParmErr
+ );
+
+ NET_API_STATUS
+ NetrServerDiskEnum (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in,out] DISK_ENUM_CONTAINER *DiskInfoStruct,
+ [in] DWORD PreferedMaximumLength,
+ [out] DWORD * TotalEntries,
+ [in,out,unique] DWORD * ResumeHandle
+ );
+
+ NET_API_STATUS
+ NetrServerStatisticsGet (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string,unique] WCHAR * Service,
+ [in] DWORD Level,
+ [in] DWORD Options,
+ [out] LPSTAT_SERVER_0 *InfoStruct
+ );
+
+ NET_API_STATUS
+ NetrServerTransportAdd (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in] LPSERVER_TRANSPORT_INFO_0 Buffer
+ );
+
+ NET_API_STATUS
+ NetrServerTransportEnum (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,out] LPSERVER_XPORT_ENUM_STRUCT InfoStruct,
+ [in] DWORD PreferedMaximumLength,
+ [out] DWORD * TotalEntries,
+ [in,out,unique] DWORD * ResumeHandle
+ );
+
+ NET_API_STATUS
+ NetrServerTransportDel (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in] LPSERVER_TRANSPORT_INFO_0 Buffer
+ );
+
+ NET_API_STATUS
+ NetrRemoteTOD (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [out] LPTIME_OF_DAY_INFO *BufferPtr
+ );
+
+// This method not used on the wire
+ void Opnum29NotUsedOnWire(void);
+
+ NET_API_STATUS
+ NetprPathType(
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * PathName,
+ [out] DWORD * PathType,
+ [in] DWORD Flags
+ );
+
+ NET_API_STATUS
+ NetprPathCanonicalize(
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * PathName,
+ [out,size_is(OutbufLen)] unsigned char * Outbuf,
+ [in,range(0, 64000)] DWORD OutbufLen,
+ [in,string] WCHAR * Prefix,
+ [in,out] DWORD * PathType,
+ [in] DWORD Flags
+ );
+
+ long
+ NetprPathCompare(
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * PathName1,
+ [in,string] WCHAR * PathName2,
+ [in] DWORD PathType,
+ [in] DWORD Flags
+ );
+
+ NET_API_STATUS
+ NetprNameValidate(
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * Name,
+ [in] DWORD NameType,
+ [in] DWORD Flags
+ );
+
+ NET_API_STATUS
+ NetprNameCanonicalize(
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * Name,
+ [out, size_is(OutbufLen)] WCHAR * Outbuf,
+ [in,range(0, 64000)] DWORD OutbufLen,
+ [in] DWORD NameType,
+ [in] DWORD Flags
+ );
+
+ long
+ NetprNameCompare(
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * Name1,
+ [in,string] WCHAR * Name2,
+ [in] DWORD NameType,
+ [in] DWORD Flags
+ );
+
+ NET_API_STATUS
+ NetrShareEnumSticky (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,out] LPSHARE_ENUM_STRUCT InfoStruct,
+ [in] DWORD PreferedMaximumLength,
+ [out] DWORD * TotalEntries,
+ [in,out,unique] DWORD * ResumeHandle
+ );
+
+ NET_API_STATUS
+ NetrShareDelStart (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * NetName,
+ [in] DWORD Reserved,
+ [out] PSHARE_DEL_HANDLE ContextHandle
+ );
+
+ NET_API_STATUS
+ NetrShareDelCommit (
+ [in, out] PSHARE_DEL_HANDLE ContextHandle
+ );
+
+ DWORD
+ NetrpGetFileSecurity (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string,unique] WCHAR * ShareName,
+ [in,string] WCHAR * lpFileName,
+ [in] SECURITY_INFORMATION RequestedInformation,
+ [out] PADT_SECURITY_DESCRIPTOR *SecurityDescriptor
+ );
+
+ DWORD
+ NetrpSetFileSecurity (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string,unique] WCHAR * ShareName,
+ [in,string] WCHAR * lpFileName,
+ [in] SECURITY_INFORMATION SecurityInformation,
+ [in] PADT_SECURITY_DESCRIPTOR SecurityDescriptor
+ );
+
+ NET_API_STATUS
+ NetrServerTransportAddEx (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in, switch_is(Level)] LPTRANSPORT_INFO Buffer
+ );
+
+// This method not used on the wire
+ void Opnum42NotUsedOnWire(void);
+
+ NET_API_STATUS
+ NetrDfsGetVersion(
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [out] DWORD * Version
+ );
+
+ NET_API_STATUS
+ NetrDfsCreateLocalPartition (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * ShareName,
+ [in] GUID * EntryUid,
+ [in,string] WCHAR * EntryPrefix,
+ [in,string] WCHAR * ShortName,
+ [in] LPNET_DFS_ENTRY_ID_CONTAINER RelationInfo,
+ [in] int Force
+ );
+
+ NET_API_STATUS
+ NetrDfsDeleteLocalPartition (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] GUID * Uid,
+ [in,string] WCHAR * Prefix
+ );
+
+ NET_API_STATUS
+ NetrDfsSetLocalVolumeState (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] GUID * Uid,
+ [in,string] WCHAR * Prefix,
+ [in] unsigned long State
+ );
+
+// This method not used on the wire
+ void Opnum47NotUsedOnWire(void);
+
+ NET_API_STATUS
+ NetrDfsCreateExitPoint (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] GUID * Uid,
+ [in,string] WCHAR * Prefix,
+ [in] unsigned long Type,
+ [in, range(0,32) ] DWORD ShortPrefixLen,
+ [out,string,size_is(ShortPrefixLen)] WCHAR * ShortPrefix
+ );
+
+ NET_API_STATUS
+ NetrDfsDeleteExitPoint (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] GUID * Uid,
+ [in,string] WCHAR * Prefix,
+ [in] unsigned long Type
+ );
+
+ NET_API_STATUS
+ NetrDfsModifyPrefix (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] GUID * Uid,
+ [in,string] WCHAR * Prefix
+ );
+
+ NET_API_STATUS
+ NetrDfsFixLocalVolume (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,string] WCHAR * VolumeName,
+ [in] unsigned long EntryType,
+ [in] unsigned long ServiceType,
+ [in,string] WCHAR * StgId,
+ [in] GUID * EntryUid,
+ [in,string] WCHAR * EntryPrefix,
+ [in] LPNET_DFS_ENTRY_ID_CONTAINER RelationInfo,
+ [in] unsigned long CreateDisposition
+ );
+
+ NET_API_STATUS
+ NetrDfsManagerReportSiteInfo (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,out,unique] LPDFS_SITELIST_INFO *ppSiteInfo
+ );
+
+ NET_API_STATUS
+ NetrServerTransportDelEx (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in, switch_is(Level)] LPTRANSPORT_INFO Buffer
+ );
+
+NET_API_STATUS
+NetrServerAliasAdd (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in, switch_is(Level)] LPSERVER_ALIAS_INFO InfoStruct
+ );
+
+NET_API_STATUS
+NetrServerAliasEnum (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in,out] LPSERVER_ALIAS_ENUM_STRUCT InfoStruct,
+ [in] DWORD PreferedMaximumLength,
+ [out] LPDWORD TotalEntries,
+ [in,out,unique] LPDWORD ResumeHandle
+ );
+
+NET_API_STATUS
+NetrServerAliasDel (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in, switch_is(Level)] LPSERVER_ALIAS_INFO InfoStruct
+ );
+
+ NET_API_STATUS
+ NetrShareDelEx (
+ [in,string,unique] SRVSVC_HANDLE ServerName,
+ [in] DWORD Level,
+ [in,switch_is(Level)] LPSHARE_INFO ShareInfo
+ );
+}
--- /dev/null
+/*
+ * Copyright 2009 Microsoft
+ *
+ * Used with permission.
+ */
+
+import "wtypes.idl";
+
+[
+ uuid(6BFFD098-A112-3610-9833-46C3F87E345A),version(1.0),
+ pointer_default(unique)
+]
+
+interface wkssvc
+{
+ typedef enum _NETSETUP_JOIN_STATUS {
+ NetSetupUnknownStatus = 0,
+ NetSetupUnjoined,
+ NetSetupWorkgroupName,
+ NetSetupDomainName
+ } NETSETUP_JOIN_STATUS, *PNETSETUP_JOIN_STATUS;
+
+ typedef enum _NETSETUP_NAME_TYPE {
+ NetSetupUnknown = 0,
+ NetSetupMachine,
+ NetSetupWorkgroup,
+ NetSetupDomain,
+ NetSetupNonExistentDomain,
+ NetSetupDnsMachine
+ } NETSETUP_NAME_TYPE, *PNETSETUP_NAME_TYPE;
+
+ typedef enum _NET_COMPUTER_NAME_TYPE {
+ NetPrimaryComputerName = 0,
+ NetAlternateComputerNames,
+ NetAllComputerNames,
+ NetComputerNameTypeMax
+ } NET_COMPUTER_NAME_TYPE, *PNET_COMPUTER_NAME_TYPE;
+
+ typedef struct _STAT_WORKSTATION_0 {
+ LARGE_INTEGER StatisticsStartTime;
+ LARGE_INTEGER BytesReceived;
+ LARGE_INTEGER SmbsReceived;
+ LARGE_INTEGER PagingReadBytesRequested;
+ LARGE_INTEGER NonPagingReadBytesRequested;
+ LARGE_INTEGER CacheReadBytesRequested;
+ LARGE_INTEGER NetworkReadBytesRequested;
+ LARGE_INTEGER BytesTransmitted;
+ LARGE_INTEGER SmbsTransmitted;
+ LARGE_INTEGER PagingWriteBytesRequested;
+ LARGE_INTEGER NonPagingWriteBytesRequested;
+ LARGE_INTEGER CacheWriteBytesRequested;
+ LARGE_INTEGER NetworkWriteBytesRequested;
+ unsigned long InitiallyFailedOperations;
+ unsigned long FailedCompletionOperations;
+ unsigned long ReadOperations;
+ unsigned long RandomReadOperations;
+ unsigned long ReadSmbs;
+ unsigned long LargeReadSmbs;
+ unsigned long SmallReadSmbs;
+ unsigned long WriteOperations;
+ unsigned long RandomWriteOperations;
+ unsigned long WriteSmbs;
+ unsigned long LargeWriteSmbs;
+ unsigned long SmallWriteSmbs;
+ unsigned long RawReadsDenied;
+ unsigned long RawWritesDenied;
+ unsigned long NetworkErrors;
+ unsigned long Sessions;
+ unsigned long FailedSessions;
+ unsigned long Reconnects;
+ unsigned long CoreConnects;
+ unsigned long Lanman20Connects;
+ unsigned long Lanman21Connects;
+ unsigned long LanmanNtConnects;
+ unsigned long ServerDisconnects;
+ unsigned long HungSessions;
+ unsigned long UseCount;
+ unsigned long FailedUseCount;
+ unsigned long CurrentCommands;
+ } STAT_WORKSTATION_0, *PSTAT_WORKSTATION_0, *LPSTAT_WORKSTATION_0;
+
+ typedef struct _WKSTA_INFO_100 {
+ unsigned long wki100_platform_id;
+ [string] wchar_t* wki100_computername;
+ [string] wchar_t* wki100_langroup;
+ unsigned long wki100_ver_major;
+ unsigned long wki100_ver_minor;
+ } WKSTA_INFO_100, *PWKSTA_INFO_100, *LPWKSTA_INFO_100;
+
+ typedef struct _WKSTA_INFO_101 {
+ unsigned long wki101_platform_id;
+ [string] wchar_t* wki101_computername;
+ [string] wchar_t* wki101_langroup;
+ unsigned long wki101_ver_major;
+ unsigned long wki101_ver_minor;
+ [string] wchar_t* wki101_lanroot;
+ } WKSTA_INFO_101, *PWKSTA_INFO_101, *LPWKSTA_INFO_101;
+
+ typedef struct _WKSTA_INFO_102 {
+ unsigned long wki102_platform_id;
+ [string] wchar_t* wki102_computername;
+ [string] wchar_t* wki102_langroup;
+ unsigned long wki102_ver_major;
+ unsigned long wki102_ver_minor;
+ [string] wchar_t* wki102_lanroot;
+ unsigned long wki102_logged_on_users;
+ } WKSTA_INFO_102, *PWKSTA_INFO_102, *LPWKSTA_INFO_102;
+
+ typedef struct _WKSTA_INFO_502{
+ unsigned long wki502_char_wait;
+ unsigned long wki502_collection_time;
+ unsigned long wki502_maximum_collection_count;
+ unsigned long wki502_keep_conn;
+ unsigned long wki502_max_cmds;
+ unsigned long wki502_sess_timeout;
+ unsigned long wki502_siz_char_buf;
+ unsigned long wki502_max_threads;
+ unsigned long wki502_lock_quota;
+ unsigned long wki502_lock_increment;
+ unsigned long wki502_lock_maximum;
+ unsigned long wki502_pipe_increment;
+ unsigned long wki502_pipe_maximum;
+ unsigned long wki502_cache_file_timeout;
+ unsigned long wki502_dormant_file_limit;
+ unsigned long wki502_read_ahead_throughput;
+ unsigned long wki502_num_mailslot_buffers;
+ unsigned long wki502_num_srv_announce_buffers;
+ unsigned long wki502_max_illegal_datagram_events;
+ unsigned long wki502_illegal_datagram_event_reset_frequency;
+ int wki502_log_election_packets;
+ int wki502_use_opportunistic_locking;
+ int wki502_use_unlock_behind;
+ int wki502_use_close_behind;
+ int wki502_buf_named_pipes;
+ int wki502_use_lock_read_unlock;
+ int wki502_utilize_nt_caching;
+ int wki502_use_raw_read;
+ int wki502_use_raw_write;
+ int wki502_use_write_raw_data;
+ int wki502_use_encryption;
+ int wki502_buf_files_deny_write;
+ int wki502_buf_read_only_files;
+ int wki502_force_core_create_mode;
+ int wki502_use_512_byte_max_transfer;
+ } WKSTA_INFO_502, *PWKSTA_INFO_502, *LPWKSTA_INFO_502;
+
+ typedef struct _WKSTA_INFO_1013 {
+ unsigned long wki1013_keep_conn;
+ } WKSTA_INFO_1013, *PWKSTA_INFO_1013, *LPWKSTA_INFO_1013;
+
+ typedef struct _WKSTA_INFO_1018 {
+ unsigned long wki1018_sess_timeout;
+ } WKSTA_INFO_1018, *PWKSTA_INFO_1018, *LPWKSTA_INFO_1018;
+
+ typedef struct _WKSTA_INFO_1046 {
+ unsigned long wki1046_dormant_file_limit;
+ } WKSTA_INFO_1046, *PWKSTA_INFO_1046, *LPWKSTA_INFO_1046;
+
+ typedef struct _WKSTA_USER_INFO_0 {
+ [string] wchar_t* wkui0_username;
+ } WKSTA_USER_INFO_0, *PWKSTA_USER_INFO_0, *LPWKSTA_USER_INFO_0;
+
+ typedef struct _WKSTA_USER_INFO_1 {
+ [string] wchar_t* wkui1_username;
+ [string] wchar_t* wkui1_logon_domain;
+ [string] wchar_t* wkui1_oth_domains;
+ [string] wchar_t* wkui1_logon_server;
+ } WKSTA_USER_INFO_1, *PWKSTA_USER_INFO_1, *LPWKSTA_USER_INFO_1;
+
+ typedef struct _WKSTA_TRANSPORT_INFO_0 {
+ unsigned long wkti0_quality_of_service;
+ unsigned long wkti0_number_of_vcs;
+ [string] wchar_t* wkti0_transport_name;
+ [string] wchar_t* wkti0_transport_address;
+ unsigned long wkti0_wan_ish;
+ } WKSTA_TRANSPORT_INFO_0, *PWKSTA_TRANSPORT_INFO_0,
+ *LPWKSTA_TRANSPORT_INFO_0;
+
+ typedef [handle] wchar_t* WKSSVC_IDENTIFY_HANDLE;
+
+ typedef [handle] wchar_t* WKSSVC_IMPERSONATE_HANDLE;
+
+ typedef [switch_type(unsigned long)] union _WKSTA_INFO {
+ [case(100)]
+ LPWKSTA_INFO_100 WkstaInfo100;
+ [case(101)]
+ LPWKSTA_INFO_101 WkstaInfo101;
+ [case(102)]
+ LPWKSTA_INFO_102 WkstaInfo102;
+ [case(502)]
+ LPWKSTA_INFO_502 WkstaInfo502;
+ [case(1013)]
+ LPWKSTA_INFO_1013 WkstaInfo1013;
+ [case(1018)]
+ LPWKSTA_INFO_1018 WkstaInfo1018;
+ [case(1046)]
+ LPWKSTA_INFO_1046 WkstaInfo1046;
+ [default]
+ ;
+ } WKSTA_INFO, *PWKSTA_INFO, *LPWKSTA_INFO;
+
+ unsigned long
+ NetrWkstaGetInfo (
+ [in,string,unique] WKSSVC_IDENTIFY_HANDLE ServerName,
+ [in] unsigned long Level,
+ [out, switch_is(Level)] LPWKSTA_INFO WkstaInfo
+ );
+
+ unsigned long
+ NetrWkstaSetInfo (
+ [in,string,unique] WKSSVC_IDENTIFY_HANDLE ServerName,
+ [in] unsigned long Level,
+ [in, switch_is(Level)] LPWKSTA_INFO WkstaInfo,
+ [in,out,unique] unsigned long* ErrorParameter
+ );
+
+ typedef struct _WKSTA_USER_INFO_0_CONTAINER {
+ unsigned long EntriesRead;
+ [size_is(EntriesRead)] LPWKSTA_USER_INFO_0 Buffer;
+ } WKSTA_USER_INFO_0_CONTAINER, *PWKSTA_USER_INFO_0_CONTAINER,
+ *LPWKSTA_USER_INFO_0_CONTAINER;
+
+ typedef struct _WKSTA_USER_INFO_1_CONTAINER {
+ unsigned long EntriesRead;
+ [size_is(EntriesRead)] LPWKSTA_USER_INFO_1 Buffer;
+ } WKSTA_USER_INFO_1_CONTAINER, *PWKSTA_USER_INFO_1_CONTAINER,
+ *LPWKSTA_USER_INFO_1_CONTAINER;
+
+
+ typedef struct _WKSTA_USER_ENUM_STRUCT {
+ unsigned long Level;
+ [switch_is(Level)] union _WKSTA_USER_ENUM_UNION {
+ [case(0)]
+ LPWKSTA_USER_INFO_0_CONTAINER Level0;
+ [case(1)]
+ LPWKSTA_USER_INFO_1_CONTAINER Level1;
+ [default]
+ ;
+ } WkstaUserInfo;
+ } WKSTA_USER_ENUM_STRUCT,
+ *PWKSTA_USER_ENUM_STRUCT,
+ *LPWKSTA_USER_ENUM_STRUCT;
+
+ unsigned long
+ NetrWkstaUserEnum (
+ [in,string,unique] WKSSVC_IDENTIFY_HANDLE ServerName,
+ [in,out] LPWKSTA_USER_ENUM_STRUCT UserInfo,
+ [in] unsigned long PreferredMaximumLength,
+ [out] unsigned long* TotalEntries,
+ [in,out,unique] unsigned long* ResumeHandle
+ );
+
+ void Opnum3NotUsedOnWire(void);
+
+ void Opnum4NotUsedOnWire(void);
+
+ typedef struct _WKSTA_TRANSPORT_INFO_0_CONTAINER {
+ unsigned long EntriesRead;
+ [size_is(EntriesRead)] LPWKSTA_TRANSPORT_INFO_0 Buffer;
+ } WKSTA_TRANSPORT_INFO_0_CONTAINER,
+ *PWKSTA_TRANSPORT_INFO_0_CONTAINER,
+ *LPWKSTA_TRANSPORT_INFO_0_CONTAINER;
+
+ typedef struct _WKSTA_TRANSPORT_ENUM_STRUCT {
+ unsigned long Level;
+ [switch_is(Level)] union _WKSTA_TRANSPORT_ENUM_UNION {
+ [case(0)]
+ LPWKSTA_TRANSPORT_INFO_0_CONTAINER Level0;
+ [default]
+ ;
+ } WkstaTransportInfo;
+ } WKSTA_TRANSPORT_ENUM_STRUCT, *PWKSTA_TRANSPORT_ENUM_STRUCT,
+ *LPWKSTA_TRANSPORT_ENUM_STRUCT;
+
+ unsigned long
+ NetrWkstaTransportEnum (
+ [in,string,unique] WKSSVC_IDENTIFY_HANDLE ServerName,
+ [in,out] LPWKSTA_TRANSPORT_ENUM_STRUCT TransportInfo,
+ [in] unsigned long PreferredMaximumLength,
+ [out] unsigned long* TotalEntries,
+ [in,out,unique] unsigned long* ResumeHandle
+ );
+
+ unsigned long
+ NetrWkstaTransportAdd (
+ [in,string,unique] WKSSVC_IDENTIFY_HANDLE ServerName,
+ [in] unsigned long Level,
+ [in] LPWKSTA_TRANSPORT_INFO_0 TransportInfo,
+ [in,out,unique] unsigned long* ErrorParameter
+ );
+
+ unsigned long
+ NetrWkstaTransportDel (
+ [in,string,unique] WKSSVC_IDENTIFY_HANDLE ServerName,
+ [in,string,unique] wchar_t* TransportName,
+ [in] unsigned long ForceLevel
+ );
+
+ void Opnum8NotUsedOnWire(void);
+
+ void Opnum9NotUsedOnWire(void);
+
+ void Opnum10NotUsedOnWire(void);
+
+ void Opnum11NotUsedOnWire(void);
+
+ void Opnum12NotUsedOnWire(void);
+
+ unsigned long
+ NetrWorkstationStatisticsGet(
+ [in,string,unique] WKSSVC_IDENTIFY_HANDLE ServerName,
+ [in,string,unique] wchar_t* ServiceName,
+ [in] unsigned long Level,
+ [in] unsigned long Options,
+ [out] LPSTAT_WORKSTATION_0* Buffer
+ );
+
+ void Opnum14NotUsedOnWire(void);
+
+ void Opnum15NotUsedOnWire(void);
+
+ void Opnum16NotUsedOnWire(void);
+
+ void Opnum17NotUsedOnWire(void);
+
+ void Opnum18NotUsedOnWire(void);
+
+ void Opnum19NotUsedOnWire(void);
+
+ unsigned long
+ NetrGetJoinInformation(
+ [in,string,unique] WKSSVC_IMPERSONATE_HANDLE ServerName,
+ [in,out,string] wchar_t** NameBuffer,
+ [out] PNETSETUP_JOIN_STATUS BufferType
+ );
+
+ void Opnum21NotUsedOnWire(void);
+
+#define JOIN_OBFUSCATOR_LENGTH 8
+#define JOIN_MAX_PASSWORD_LENGTH 256
+
+ typedef struct _JOINPR_USER_PASSWORD {
+ unsigned char Obfuscator[JOIN_OBFUSCATOR_LENGTH];
+ wchar_t Buffer[JOIN_MAX_PASSWORD_LENGTH];
+ unsigned long Length;
+ } JOINPR_USER_PASSWORD,
+ *PJOINPR_USER_PASSWORD;
+
+ typedef struct _JOINPR_ENCRYPTED_USER_PASSWORD {
+ unsigned char Buffer[JOIN_OBFUSCATOR_LENGTH +
+ (JOIN_MAX_PASSWORD_LENGTH * sizeof(wchar_t)) +
+ sizeof(unsigned long)];
+ } JOINPR_ENCRYPTED_USER_PASSWORD,
+ *PJOINPR_ENCRYPTED_USER_PASSWORD;
+
+ typedef struct _UNICODE_STRING {
+ unsigned short Length;
+ unsigned short MaximumLength;
+ [size_is(MaximumLength / 2), length_is((Length) / 2)]
+ unsigned short* Buffer;
+ } UNICODE_STRING,
+ *PUNICODE_STRING;
+
+ unsigned long
+ NetrJoinDomain2(
+ [in] handle_t RpcBindingHandle,
+ [in,string,unique] wchar_t* ServerName,
+ [in,string] wchar_t* DomainName,
+ [in,string,unique] wchar_t* MachineAccountOU,
+ [in,string,unique] wchar_t* AccountName,
+ [in,unique] PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ [in] unsigned long Options
+ );
+
+ unsigned long
+ NetrUnjoinDomain2(
+ [in] handle_t RpcBindingHandle,
+ [in,string,unique] wchar_t* ServerName,
+ [in,string,unique] wchar_t* AccountName,
+ [in,unique] PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ [in] unsigned long Options
+ );
+
+ unsigned long
+ NetrRenameMachineInDomain2(
+ [in] handle_t RpcBindingHandle,
+ [in,string,unique] wchar_t* ServerName,
+ [in,string,unique] wchar_t* MachineName,
+ [in,string,unique] wchar_t* AccountName,
+ [in,unique] PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ [in] unsigned long Options
+ );
+
+ unsigned long
+ NetrValidateName2(
+ [in] handle_t RpcBindingHandle,
+ [in,string,unique] wchar_t* ServerName,
+ [in,string] wchar_t* NameToValidate,
+ [in,string,unique] wchar_t* AccountName,
+ [in,unique] PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ [in] NETSETUP_NAME_TYPE NameType
+ );
+
+ unsigned long
+ NetrGetJoinableOUs2(
+ [in] handle_t RpcBindingHandle,
+ [in,string,unique] wchar_t* ServerName,
+ [in,string] wchar_t* DomainName,
+ [in,string,unique] wchar_t* AccountName,
+ [in,unique] PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ [in,out] unsigned long* OUCount,
+ [out,string,size_is(,*OUCount)] wchar_t*** OUs
+ );
+
+ unsigned long
+ NetrAddAlternateComputerName(
+ [in] handle_t RpcBindingHandle,
+ [in,string,unique] wchar_t* ServerName,
+ [in,string,unique] wchar_t* AlternateName,
+ [in,string,unique] wchar_t* DomainAccount,
+ [in,unique] PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
+ [in] unsigned long Reserved
+ );
+
+ unsigned long
+ NetrRemoveAlternateComputerName(
+ [in] handle_t RpcBindingHandle,
+ [in,string,unique] wchar_t* ServerName,
+ [in,string,unique] wchar_t* AlternateName,
+ [in,string,unique] wchar_t* DomainAccount,
+ [in,unique] PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
+ [in] unsigned long Reserved
+ );
+
+ unsigned long
+ NetrSetPrimaryComputerName(
+ [in] handle_t RpcBindingHandle,
+ [in,string,unique] wchar_t* ServerName,
+ [in,string,unique] wchar_t* PrimaryName,
+ [in,string,unique] wchar_t* DomainAccount,
+ [in,unique] PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
+ [in] unsigned long Reserved
+ );
+
+ typedef struct _NET_COMPUTER_NAME_ARRAY {
+ unsigned long EntryCount;
+ [size_is(EntryCount)] PUNICODE_STRING ComputerNames;
+ } NET_COMPUTER_NAME_ARRAY, *PNET_COMPUTER_NAME_ARRAY;
+
+ unsigned long
+ NetrEnumerateComputerNames(
+ [in,string,unique] WKSSVC_IMPERSONATE_HANDLE ServerName,
+ [in] NET_COMPUTER_NAME_TYPE NameType,
+ [in] unsigned long Reserved,
+ [out] PNET_COMPUTER_NAME_ARRAY *ComputerNames
+ );
+}
--- /dev/null
+/*
+ * Copyright (c) 2009 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <malloc.h>
+#include "ms-wkssvc.h"
+#include "ms-srvsvc.h"
+#include "afsd.h"
+#include "cm_btree.h"
+#include "msrpc.h"
+
+static void
+MSRPC_AllocBuffer(msrpc_buffer * buf, unsigned int size);
+
+static void
+MSRPC_ReallocBuffer(msrpc_buffer * buf, unsigned int size);
+
+static void
+MSRPC_FreeBuffer(msrpc_buffer * buf);
+
+static void
+MSRPC_SetCmUser(cm_user_t * userp);
+
+/*! \brief Interface list
+
+ This is the list of interfaces that are exported through this RPC
+ module. The *_ifspec variable is defined the <interface>_s.c file
+ that is generated by MIDL. We have to use an extra level of
+ indirection because the actual RPC_SERVER_INTERFACE structure is
+ not exported in the generated code.
+ */
+RPC_SERVER_INTERFACE **_Interfaces[] = {
+ (RPC_SERVER_INTERFACE **) &wkssvc_v1_0_s_ifspec,
+ (RPC_SERVER_INTERFACE **) &srvsvc_v3_0_s_ifspec,
+};
+
+const int n_Interfaces = sizeof(_Interfaces)/sizeof(_Interfaces[0]);
+
+/* Serialization */
+
+#define RPC_ALIGNMENT 8
+#define ALIGNTO8(x) (((((x) - 1)/8) + 1) * 8)
+
+typedef struct fcursor {
+ BYTE * pos;
+ BYTE * end;
+} fcursor;
+
+#define INITC(pfc, buf, len) (pfc)->pos = (BYTE *)(buf); (pfc)->end = (pfc)->pos + (len)
+
+#define SPC_LEFT(pfc) ((unsigned int)((pfc)->end - (pfc)->pos))
+#define IS_SPC(pfc, n) (SPC_LEFT(pfc) >= (n))
+
+__inline BYTE READB(fcursor * pfc) {
+ BYTE b = *pfc->pos;
+ pfc->pos++;
+ return b;
+}
+
+#define READW(pfc) (((WORD)READB(pfc)) | (((WORD)READB(pfc)) << 8))
+#define READDW(pfc) (((DWORD)READW(pfc)) | (((DWORD)READW(pfc)) << 16))
+#define O_READS(pfc, s) do { memcpy(s, (pfc)->pos, sizeof(*s)); (pfc)->pos += sizeof(*s); } while (0)
+#define O_READA(pfc, a) do { memcpy(&a, (pfc)->pos, sizeof(a)); (pfc)->pos += sizeof(a); } while (0)
+#define O_READSZ(pfc, s, sz) do { memcpy(s, (pfc)->pos, sz); (pfc)->pos += sz; } while (0)
+#define O_RALIGN4(pfc) do { while(((size_t) (pfc)->pos) & 0x3) READB(pfc); } while (0)
+#define O_RALIGN8(pfc) do { while(((size_t) (pfc)->pos) & 0x7) READB(pfc); } while (0)
+
+__inline void WRITEB(fcursor * pfc, BYTE b) {
+ *pfc->pos = b;
+ pfc->pos++;
+}
+
+#define WRITEW(pfc, w) (WRITEB(pfc, ((w) & 0xff)), WRITEB(pfc, (((w) >> 8) & 0xff)))
+#define WRITEDW(pfc, dw) (WRITEW(pfc, ((dw) & 0xffff)), WRITEW(pfc, (((dw) >> 16) & 0xffff)))
+#define O_WRITES(pfc, s) do { memcpy((pfc)->pos, s, sizeof(*s)); (pfc)->pos += sizeof(*s); } while (0)
+#define O_WRITEA(pfc, a) do { memcpy((pfc)->pos, &a, sizeof(a)); (pfc)->pos += sizeof(a); } while (0)
+#define O_WRITESZ(pfc, s, sz) do { memcpy((pfc)->pos, s, sz); (pfc)->pos += sz; } while (0)
+#define O_WALIGN4(pfc) do { while(((size_t) (pfc)->pos) & 0x3) WRITEB(pfc, 0); } while (0)
+#define O_WALIGN8(pfc) do { while(((size_t) (pfc)->pos) & 0x7) WRITEB(pfc, 0); } while (0)
+
+#define iread_u_int8(pfc) READB(pfc)
+#define iread_byte(pfc) READB(pfc)
+#define iread_u_int16(pfc) READW(pfc)
+#define iread_u_int32(pfc) READDW(pfc)
+
+#define write_u_int8(pfc, i) WRITEB(pfc, i)
+#define write_byte(pfc, i) WRITEB(pfc, i)
+#define write_u_int16(pfc, i) WRITEW(pfc, i)
+#define write_u_int32(pfc, i) WRITEDW(pfc, i)
+
+/*! \brief Supported RPC protocol version numbers */
+RPC_VERSION msrpc_supported_protocol_versions[] = {
+ { 5, 0 }, /* 5.0 */
+ { 5, 1 } /* 5.1 */
+};
+
+const int n_msrpc_supported_protocol_versions = sizeof(msrpc_supported_protocol_versions)/sizeof(msrpc_supported_protocol_versions[0]);
+
+#define IS_PROTOCOL_VER_SUPPORTED(_maj, _min) ((_maj) == 5 && ((_min) == 0 || (_min) == 1))
+
+/*! \brief Number of bytes of envelope overhead for an RPC response PDU */
+#define RPC_RESPONSE_ENVELOPE_OVERHEAD 24
+
+static int
+read_E_CommonHeader(fcursor *pc, E_CommonHeader * pr)
+{
+ if (IS_SPC(pc, 16)) {
+
+ pr->rpc_vers = iread_u_int8(pc);
+ pr->rpc_vers_minor = iread_u_int8(pc);
+ pr->PTYPE = iread_u_int8(pc);
+ pr->pfc_flags = iread_u_int8(pc);
+ O_READA(pc, pr->packed_drep);
+ pr->frag_length = iread_u_int16(pc);
+ pr->auth_length = iread_u_int16(pc);
+ pr->call_id = iread_u_int32(pc);
+
+ return 0;
+
+ } else {
+ return CM_ERROR_BADFORMAT;
+ }
+}
+
+static int
+write_E_CommonHeader(fcursor * pc, msrpc_conn * conn,
+ msrpc_call * call, PDU_TYPE pdu_type)
+{
+ INITC(pc, call->out.buf_data, call->out.buf_alloc);
+
+ call->out.pdu_type = pdu_type;
+
+ if (IS_SPC(pc, 16)) {
+ write_u_int8(pc, conn->rpc_vers); /* protocol version */
+ write_u_int8(pc, conn->rpc_vers_minor); /* minor version */
+ write_u_int8(pc, pdu_type);
+ write_u_int8(pc, PFC_FIRST_FRAG|PFC_LAST_FRAG);
+
+ write_byte(pc, 0x10); /* Data representation */
+ write_byte(pc, 0);
+ write_byte(pc, 0);
+ write_byte(pc, 0);
+
+ write_u_int16(pc, 0); /* Fragment ength, to be filled in
+ later */
+ write_u_int16(pc, 0); /* Length of auth data. Always 0 since
+ we don't do authentication for RPC
+ calls.*/
+ write_u_int32(pc, call->call_id);
+
+ return 0;
+ } else {
+ return CM_ERROR_BUFFERTOOSMALL;
+ }
+}
+
+#define USE_CURRENT_BUFFER_LENGTH (-1)
+static int
+closeMessage(fcursor * pc, msrpc_call * call, ptrdiff_t len)
+{
+
+ unsigned short slen;
+
+ if (len == USE_CURRENT_BUFFER_LENGTH)
+ len = pc->pos - call->out.buf_data;
+
+ if (len >= USHRT_MAX)
+ return CM_ERROR_TOOBIG;
+ slen = (unsigned short)len;
+
+ pc->pos = &call->out.buf_data[8];
+ write_u_int16(pc, slen);
+ call->out.buf_length = slen;
+
+ return 0;
+}
+
+static int
+read_UUID(fcursor * pc,
+ UUID * uuid)
+{
+ if (IS_SPC(pc, sizeof(*uuid))) {
+ O_READS(pc, uuid);
+ return 0;
+ } else {
+ return CM_ERROR_BADFORMAT;
+ }
+}
+
+static int
+write_UUID(fcursor * pc,
+ const UUID * uuid)
+{
+ if (IS_SPC(pc, sizeof(*uuid))) {
+ O_WRITES(pc, uuid);
+ return 0;
+ } else {
+ return CM_ERROR_BUFFERTOOSMALL;
+ }
+}
+
+static int
+read_RPC_VERSION(fcursor * pc,
+ RPC_VERSION * ver)
+{
+ if (IS_SPC(pc, 4)) {
+ ver->MajorVersion = iread_u_int16(pc);
+ ver->MinorVersion = iread_u_int16(pc);
+ return 0;
+ } else {
+ return CM_ERROR_BADFORMAT;
+ }
+}
+
+static int
+write_RPC_VERSION(fcursor * pc,
+ const RPC_VERSION * ver)
+{
+ if (IS_SPC(pc, 4)) {
+ write_u_int16(pc, ver->MajorVersion);
+ write_u_int16(pc, ver->MinorVersion);
+ return 0;
+ } else {
+ return CM_ERROR_BUFFERTOOSMALL;
+ }
+}
+
+static int
+read_RPC_SYNTAX_IDENTIFIER(fcursor * pc,
+ RPC_SYNTAX_IDENTIFIER * psi)
+{
+ int code;
+
+ code = read_UUID(pc, &psi->SyntaxGUID);
+ if (code)
+ return code;
+ code = read_RPC_VERSION(pc, &psi->SyntaxVersion);
+ return code;
+}
+
+static int
+write_RPC_SYNTAX_IDENTIFIER(fcursor * pc,
+ const RPC_SYNTAX_IDENTIFIER * psi)
+{
+ int code;
+
+ code = write_UUID(pc, &psi->SyntaxGUID);
+ if (code)
+ return code;
+ code = write_RPC_VERSION(pc, &psi->SyntaxVersion);
+ return code;
+}
+
+static int
+is_equal_RPC_SYNTAX_IDENTIFIER(const RPC_SYNTAX_IDENTIFIER * s1,
+ const RPC_SYNTAX_IDENTIFIER * s2)
+{
+ return
+ IsEqualGUID(&s1->SyntaxGUID, &s2->SyntaxGUID) &&
+ s1->SyntaxVersion.MajorVersion == s2->SyntaxVersion.MajorVersion &&
+ s2->SyntaxVersion.MinorVersion == s2->SyntaxVersion.MinorVersion;
+}
+
+#define FAULT_PDU_PACKET_SIZE 32
+
+/*! \brief Write a fault PDU as the output of this call */
+static int
+write_fault_PDU(msrpc_conn * conn, msrpc_call * call,
+ u_int32 status, u_int8 flags)
+{
+ fcursor o;
+
+ MSRPC_AllocBuffer(&call->out, FAULT_PDU_PACKET_SIZE);
+
+ write_E_CommonHeader(&o, conn, call, PDU_TYPE_FAULT);
+
+ write_u_int32(&o, 16); /* allocation hint */
+ write_u_int16(&o, call->context_id); /* presentation context ID */
+
+ write_u_int8(&o, 0); /* cancel count */
+ write_u_int8(&o, 0); /* reserved */
+
+ write_u_int32(&o, status); /* status code */
+
+ O_WALIGN8(&o); /* alignment */
+
+ closeMessage(&o, call, USE_CURRENT_BUFFER_LENGTH);
+
+ if (flags) {
+ call->out.buf_data[3] |= flags;
+ }
+
+ call->status = MSRPC_CALL_DISPATCHED;
+
+ return 0;
+}
+
+#define BIND_NAK_PDU_PACKET_SIZE 18
+
+/*! \brief Write a bind_nak PDU as the output of this call */
+static int
+write_bind_nak_PDU(msrpc_conn * conn, msrpc_call * call,
+ BIND_REJECT_REASON reject_reason)
+{
+ fcursor o;
+ unsigned buf_size = BIND_NAK_PDU_PACKET_SIZE;
+
+ if (reject_reason == BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED)
+ buf_size += n_msrpc_supported_protocol_versions * 2 + 1;
+
+ MSRPC_AllocBuffer(&call->out, buf_size);
+
+ write_E_CommonHeader(&o, conn, call, PDU_TYPE_BIND_NAK);
+
+ write_u_int16(&o, reject_reason);
+
+ if (reject_reason == BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED) {
+ int i;
+
+ write_u_int8(&o, n_msrpc_supported_protocol_versions);
+
+ for (i=0; i < n_msrpc_supported_protocol_versions; i++) {
+ write_u_int8(&o, (u_int8) msrpc_supported_protocol_versions[i].MajorVersion);
+ write_u_int8(&o, (u_int8) msrpc_supported_protocol_versions[i].MinorVersion);
+ }
+ }
+
+ closeMessage(&o, call, USE_CURRENT_BUFFER_LENGTH);
+
+ call->status = MSRPC_CALL_DISPATCHED;
+
+ return 0;
+}
+
+static int
+handle_ConnBind(msrpc_conn * conn, msrpc_call * call, fcursor * in, fcursor * out)
+{
+ int code = 0;
+
+ if (!IS_SPC(in, 12))
+ return CM_ERROR_BADFORMAT;
+
+ conn->max_xmit_frag = iread_u_int16(in);
+ conn->max_recv_frag = iread_u_int16(in);
+ conn->assoc_group_id = iread_u_int32(in);
+
+ conn->rpc_vers = call->in_header->rpc_vers;
+ conn->rpc_vers_minor = call->in_header->rpc_vers_minor;
+
+ if (conn->assoc_group_id == 0)
+ conn->assoc_group_id = 1;
+
+ write_E_CommonHeader(out, conn, call, PDU_TYPE_BIND_ACK);
+
+ write_u_int16(out, conn->max_xmit_frag);
+ write_u_int16(out, conn->max_recv_frag);
+ write_u_int32(out, conn->assoc_group_id);
+
+ if (conn->secondary_address) {
+ int len = (int)strlen(conn->secondary_address) + 1;
+
+ write_u_int16(out, len);
+ O_WRITESZ(out, conn->secondary_address, len);
+ } else {
+ write_u_int16(out, 0);
+ }
+
+ O_WALIGN4(out);
+
+ /* presentation context negotiation */
+ {
+ int n_context_elem;
+ int i;
+
+ n_context_elem = iread_u_int8(in);
+ iread_u_int8(in); /* skip over reserved */
+ iread_u_int16(in); /* skip over reserved */
+
+ write_u_int8(out, n_context_elem);
+ write_u_int8(out, 0); /* pad */
+ write_u_int16(out, 0); /* pad */
+
+ for (i=0; i < n_context_elem; i++) {
+ int n_transfer_syn;
+ RPC_SYNTAX_IDENTIFIER abstract_syntax;
+ RPC_SYNTAX_IDENTIFIER transfer_syntax;
+ RPC_SERVER_INTERFACE *interf = NULL;
+ int j, k;
+
+ if (!IS_SPC(in, 4 + 16))
+ return CM_ERROR_BADFORMAT;
+
+ call->context_id = iread_u_int16(in);
+ n_transfer_syn = iread_u_int8(in);
+ iread_u_int8(in); /* skip */
+
+ code = read_RPC_SYNTAX_IDENTIFIER(in, &abstract_syntax);
+ if (code)
+ return code;
+
+ for (j=0; j < n_Interfaces; j++) {
+ interf = *_Interfaces[j];
+
+ if (is_equal_RPC_SYNTAX_IDENTIFIER(&abstract_syntax, &interf->InterfaceId))
+ break;
+ }
+
+ if (j < n_Interfaces) {
+ for (k=0; k < n_transfer_syn; k++) {
+ code = read_RPC_SYNTAX_IDENTIFIER(in, &transfer_syntax);
+ if (code)
+ return code;
+
+ if (is_equal_RPC_SYNTAX_IDENTIFIER(&transfer_syntax, &interf->TransferSyntax))
+ break;
+ }
+ }
+
+ if (j < n_Interfaces && k < n_transfer_syn) {
+ /* accepted */
+ write_u_int16(out, 0);
+ write_u_int16(out, 0);
+ write_RPC_SYNTAX_IDENTIFIER(out, &transfer_syntax);
+
+ conn->interface = interf;
+ } else {
+ int reason;
+
+ if (j >= n_Interfaces)
+ reason = 1; /* abstract syntax not supported */
+ else
+ reason = 2; /* transfer syntax not supported */
+ write_u_int16(out, 2); /* provider rejection */
+ write_u_int16(out, reason);
+ ZeroMemory(&transfer_syntax, sizeof(transfer_syntax));
+ write_RPC_SYNTAX_IDENTIFIER(out, &transfer_syntax);
+ }
+ }
+ }
+
+ return closeMessage(out, call, USE_CURRENT_BUFFER_LENGTH);
+}
+
+static int
+handle_ConnRequest(msrpc_conn * conn, msrpc_call * call, fcursor * in, fcursor * out)
+{
+ int code = 0;
+
+ int alloc_hint;
+ unsigned int op_num;
+ RPC_STATUS _Status = RPC_S_OK;
+
+ int len;
+
+ if (!IS_SPC(in, 8))
+ return CM_ERROR_BADFORMAT;
+
+ alloc_hint = iread_u_int32(in);
+ call->context_id = iread_u_int16(in);
+ op_num = iread_u_int16(in);
+
+ if (call->in_header->pfc_flags & PFC_OBJECT_UUID) {
+ UUID uuid;
+
+ code = read_UUID(in, &uuid);
+ if (code)
+ return code;
+ }
+
+ O_RALIGN8(in);
+
+ if (conn->interface == NULL) {
+ /* if there was no interface selected, we can't go ahead with
+ this request. */
+ return write_fault_PDU(conn, call, RPC_S_NO_BINDINGS, PFC_DID_NOT_EXECUTE);
+ }
+
+ len = SPC_LEFT(in);
+
+ if (op_num < 0 || op_num >= conn->interface->DispatchTable->DispatchTableCount ||
+ conn->interface->DispatchTable->DispatchTable[op_num] == NULL) {
+
+ return write_fault_PDU(conn, call, RPC_S_PROCNUM_OUT_OF_RANGE, PFC_DID_NOT_EXECUTE);
+ }
+
+ call->msg.BufferLength = len;
+ call->msg.ProcNum = op_num;
+ call->msg.TransferSyntax = &conn->interface->TransferSyntax;
+ call->msg.RpcInterfaceInformation = conn->interface;
+
+ _Status = I_RpcGetBuffer(&call->msg);
+ if ( _Status || call->msg.Buffer == NULL) {
+ return write_fault_PDU(conn, call, RPC_S_SERVER_OUT_OF_MEMORY, PFC_DID_NOT_EXECUTE);
+ }
+
+ memcpy(call->msg.Buffer, in->pos, len);
+
+ MSRPC_SetCmUser(call->cm_userp);
+
+ RpcTryExcept
+ {
+ (*conn->interface->DispatchTable->DispatchTable[op_num])(&call->msg);
+ }
+ RpcExcept ( 1 )
+ {
+ code = CM_ERROR_UNKNOWN;
+ }
+ RpcEndExcept;
+
+ MSRPC_SetCmUser(NULL);
+
+ if (code == 0) {
+ call->out.pdu_type = PDU_TYPE_RESPONSE;
+
+ MSRPC_AllocBuffer(&call->out, call->msg.BufferLength);
+ call->out.buf_length = call->msg.BufferLength;
+ memcpy(call->out.buf_data, call->msg.Buffer, call->out.buf_length);
+ } else {
+ code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, 0);
+ }
+
+ return code;
+}
+
+static int
+merge_fragment_Bind(msrpc_call * call, E_CommonHeader * ph,
+ msrpc_call * ncall, E_CommonHeader *pnh)
+{
+ if (ph->auth_length + (unsigned int) pnh->auth_length > _UI16_MAX ||
+ ph->frag_length + (unsigned int) pnh->auth_length > _UI16_MAX ||
+ pnh->auth_length + 16 > pnh->frag_length)
+ return CM_ERROR_TOOBIG;
+
+ MSRPC_ReallocBuffer(&call->in, call->in.buf_length + pnh->auth_length);
+ if (call->in.buf_data == NULL)
+ return CM_ERROR_TOOBIG;
+
+ memcpy(call->in.buf_data + ph->frag_length,
+ ncall->in.buf_data + (pnh->frag_length - pnh->auth_length),
+ pnh->auth_length);
+
+ call->in.buf_length += pnh->auth_length;
+ ph->frag_length += pnh->auth_length;
+ ph->auth_length += pnh->auth_length;
+
+ if ((pnh->pfc_flags & PFC_LAST_FRAG) == PFC_LAST_FRAG) {
+ ph->pfc_flags |= PFC_LAST_FRAG;
+ }
+
+ return 0;
+}
+
+static int
+merge_fragment_Request(msrpc_call * call, E_CommonHeader * ph,
+ msrpc_call * ncall, E_CommonHeader * pnh)
+{
+ int new_auth_length = pnh->auth_length;
+ int new_stub_length = (int)pnh->frag_length - (pnh->auth_length + 24);
+
+ if (pnh->pfc_flags & PFC_OBJECT_UUID)
+ new_stub_length -= 16;
+
+ if (ph->auth_length + new_auth_length > _UI16_MAX ||
+ ph->frag_length + new_stub_length + new_auth_length > _UI16_MAX ||
+ pnh->auth_length + 24 > pnh->frag_length)
+ return CM_ERROR_TOOBIG;
+
+ MSRPC_ReallocBuffer(&call->in, call->in.buf_length + new_auth_length + new_stub_length);
+ if (call->in.buf_data == NULL)
+ return CM_ERROR_TOOBIG;
+
+ if(ph->auth_length)
+ memmove(call->in.buf_data + (ph->frag_length - ph->auth_length),
+ call->in.buf_data + (ph->frag_length - ph->auth_length) + new_stub_length,
+ ph->auth_length);
+
+ memcpy(call->in.buf_data + (ph->frag_length - ph->auth_length),
+ ncall->in.buf_data + (pnh->frag_length - (new_auth_length + new_stub_length)),
+ new_stub_length);
+
+ memcpy(call->in.buf_data + ph->frag_length + new_stub_length,
+ ncall->in.buf_data + (pnh->frag_length - pnh->auth_length),
+ pnh->auth_length);
+
+ call->in.buf_length += new_auth_length + new_stub_length;
+ ph->frag_length += new_auth_length + new_stub_length;
+ ph->auth_length += new_auth_length;
+
+ if ((pnh->pfc_flags & PFC_LAST_FRAG) == PFC_LAST_FRAG) {
+ ph->pfc_flags |= PFC_LAST_FRAG;
+ }
+
+ return 0;
+}
+
+static int
+assemble_message(msrpc_conn * conn)
+{
+ int code = 0;
+ msrpc_call * call;
+ msrpc_call * ncall;
+ E_CommonHeader h;
+ fcursor c;
+
+ call = conn->head;
+
+ if (call == NULL)
+ return CM_ERROR_INVAL;
+
+ INITC(&c, call->in.buf_data, call->in.buf_length);
+
+ code = read_E_CommonHeader(&c, &h);
+ if (code)
+ return code;
+
+ if ((h.pfc_flags & (PFC_FIRST_FRAG | PFC_LAST_FRAG)) ==
+ (PFC_FIRST_FRAG | PFC_LAST_FRAG))
+ return 0;
+
+ if ((h.pfc_flags & PFC_FIRST_FRAG) != PFC_FIRST_FRAG)
+ return CM_ERROR_INVAL;
+
+ for (ncall = call->next; ncall; ncall = ncall->next) {
+ fcursor nc;
+ E_CommonHeader nh;
+
+ INITC(&nc, ncall->in.buf_data, ncall->in.buf_length);
+
+ code = read_E_CommonHeader(&nc, &nh);
+
+ if (nh.call_id != h.call_id)
+ continue;
+
+ if ((nh.pfc_flags & PFC_FIRST_FRAG) != 0)
+ continue;
+
+ switch(h.PTYPE) {
+ case PDU_TYPE_BIND:
+ case PDU_TYPE_ALTER_CONTEXT:
+ code = merge_fragment_Bind(call, &h, ncall, &nh);
+ break;
+
+ case PDU_TYPE_REQUEST:
+ code = merge_fragment_Request(call, &h, ncall, &nh);
+ break;
+
+ default:
+ code = CM_ERROR_INVAL;
+ }
+
+ ncall->status = MSRPC_CALL_SKIP;
+
+ if (nh.pfc_flags & PFC_LAST_FRAG) {
+ break;
+ }
+ }
+
+ c.pos = &call->in.buf_data[3];
+ write_u_int8(&c, h.pfc_flags);
+ write_u_int16(&c, h.frag_length);
+ write_u_int16(&c, h.auth_length);
+
+ return code;
+}
+
+static int
+dispatch_call(msrpc_conn * conn)
+{
+ int code = 0;
+ fcursor c;
+ fcursor o;
+ E_CommonHeader h;
+ msrpc_call * call;
+
+ call = conn->head;
+
+ if (call == NULL ||
+ call->status != MSRPC_CALL_MSGRECEIVED)
+ return CM_ERROR_INVAL;
+
+ MSRPC_AllocBuffer(&call->out, DEF_RPC_MSG_SIZE);
+
+ retry_buffer:
+
+ INITC(&c, call->in.buf_data, call->in.buf_length);
+
+ code = read_E_CommonHeader(&c, &h);
+ if (code)
+ return code;
+
+ if (!IS_PROTOCOL_VER_SUPPORTED(h.rpc_vers, h.rpc_vers_minor)) {
+ if (h.PTYPE == PDU_TYPE_BIND) {
+ return write_bind_nak_PDU(conn, call, BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED);
+ } else {
+ /* we shouldn't get here, but just in case */
+ return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
+ }
+ }
+
+ if (h.packed_drep[0] != 0x10 ||
+ h.packed_drep[1] != 0 ||
+ h.packed_drep[2] != 0 ||
+ h.packed_drep[3] != 0) {
+
+ if (h.PTYPE == PDU_TYPE_BIND) {
+ return write_bind_nak_PDU(conn, call, BIND_REJ_REASON_NOT_SPECIFIED);
+ } else {
+ return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
+ }
+ }
+
+ if (h.frag_length > call->in.buf_length) {
+ return CM_ERROR_INVAL;
+ }
+
+ if ((h.pfc_flags & (PFC_FIRST_FRAG | PFC_LAST_FRAG)) !=
+ (PFC_FIRST_FRAG | PFC_LAST_FRAG)) {
+ code = assemble_message(conn);
+ if (code == 0)
+ goto retry_buffer;
+ else
+ return write_fault_PDU(conn, call, RPC_S_INVALID_ARG, PFC_DID_NOT_EXECUTE);
+ }
+
+ if (h.auth_length != 0) {
+ return write_fault_PDU(conn, call, RPC_S_BINDING_HAS_NO_AUTH, PFC_DID_NOT_EXECUTE);
+ }
+
+ call->call_id = h.call_id;
+
+ call->in.pdu_type = h.PTYPE;
+
+ INITC(&o, call->out.buf_data, call->out.buf_alloc);
+
+ call->in_header = &h;
+
+ code = CM_ERROR_INVAL;
+
+ switch (h.PTYPE) {
+ case PDU_TYPE_REQUEST:
+ code = handle_ConnRequest(conn, call, &c, &o);
+ break;
+
+ case PDU_TYPE_BIND:
+ code = handle_ConnBind(conn, call, &c, &o);
+ break;
+
+ case PDU_TYPE_ALTER_CONTEXT:
+ code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
+ break;
+
+ case PDU_TYPE_SHUTDOWN:
+ code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
+ break;
+
+ case PDU_TYPE_CO_CANCEL:
+ code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
+ break;
+
+ case PDU_TYPE_ORPHANED:
+ code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
+ break;
+
+ default:
+ code = write_fault_PDU(conn, call, RPC_S_CALL_FAILED, PFC_DID_NOT_EXECUTE);
+ }
+
+ call->in_header = NULL;
+
+ call->status = MSRPC_CALL_DISPATCHED;
+
+ return code;
+}
+
+static void
+MSRPC_AllocBuffer(msrpc_buffer * buf, unsigned int size)
+{
+ if (buf->buf_alloc < size) {
+ if (buf->buf_data)
+ _aligned_free(buf->buf_data);
+
+ buf->buf_alloc = ALIGNTO8(size);
+ buf->buf_data = _aligned_malloc(buf->buf_alloc, RPC_ALIGNMENT);
+ buf->buf_length = 0;
+ buf->buf_pos = 0;
+ }
+}
+
+static void
+MSRPC_FreeBuffer(msrpc_buffer * buf)
+{
+ if (buf->buf_data) {
+ _aligned_free(buf->buf_data);
+ buf->buf_data = NULL;
+ buf->buf_alloc = 0;
+ buf->buf_length = 0;
+ buf->buf_pos = 0;
+ }
+}
+
+static void
+MSRPC_ReallocBuffer(msrpc_buffer * buf, unsigned int size)
+{
+ if (buf->buf_alloc < size) {
+ BYTE * new_buf;
+
+ buf->buf_alloc = ALIGNTO8(size);
+ new_buf = _aligned_realloc(buf->buf_data, buf->buf_alloc, RPC_ALIGNMENT);
+ if (new_buf != NULL) {
+ buf->buf_data = new_buf;
+ } else {
+ MSRPC_FreeBuffer(buf);
+ }
+ }
+}
+
+static msrpc_call *
+MSRPC_NewCall(void)
+{
+ msrpc_call * c;
+
+ c = calloc(sizeof(*c), 1);
+
+ c->msg.Handle = NULL;
+ c->msg.DataRepresentation = 0x00000010;
+ c->msg.Buffer = NULL;
+ c->msg.BufferLength = 0;
+ c->msg.TransferSyntax = NULL;
+
+ return c;
+}
+
+static int
+MSRPC_PutCall(msrpc_conn * conn, msrpc_call * pcall)
+{
+ if (conn->tail) {
+ conn->tail->next = pcall;
+ pcall->prev = conn->tail;
+ conn->tail = pcall;
+ pcall->next = NULL;
+ } else {
+ conn->head = conn->tail = pcall;
+ pcall->next = pcall->prev = NULL;
+ }
+ return 0;
+}
+
+static int
+MSRPC_DequeueCall(msrpc_conn * conn, msrpc_call * call)
+{
+ if (call->prev)
+ call->prev->next = call->next;
+ if (call->next)
+ call->next->prev = call->prev;
+
+ if (conn->head && conn->head == call)
+ conn->head = call->next;
+
+ if (conn->tail && conn->tail == call)
+ conn->tail = call->prev;
+
+ call->next = call->prev = NULL;
+
+ return 0;
+}
+
+static int
+MSRPC_GetCall(msrpc_conn * conn, msrpc_call ** ppcall)
+{
+ if (conn->head) {
+ *ppcall = conn->head;
+ conn->head = conn->head->next;
+ if (conn->head)
+ conn->head->prev = NULL;
+ (*ppcall)->next = (*ppcall)->prev = NULL;
+ if (conn->tail == *ppcall)
+ conn->tail = NULL;
+ return 0;
+ } else {
+ *ppcall = NULL;
+ return 1;
+ }
+}
+
+static int
+MSRPC_FreeCall(msrpc_call * call)
+{
+ I_RpcFreeBuffer(&call->msg);
+ MSRPC_FreeBuffer(&call->in);
+ MSRPC_FreeBuffer(&call->out);
+
+ if (call->cm_userp) {
+ cm_ReleaseUser(call->cm_userp);
+ call->cm_userp = NULL;
+ }
+
+ ZeroMemory(call, sizeof(*call));
+ free (call);
+ return 0;
+}
+
+/*! \brief Initialize a msrpc_conn
+
+ \param [out] conn Connection to initialize
+
+ \param [in] secondary_address An optional secondary address for the
+ query. Typically for RPCs to wellknown endpoints such as
+ SRVSVC or WKSSVC, this is a named pipe address (e.g.:
+ \PIPE\srvsvc ).
+
+ \return Always returns 0.
+ */
+int
+MSRPC_InitConn(msrpc_conn * conn, const char * secondary_address)
+{
+ ZeroMemory(conn, sizeof(*conn));
+ if (secondary_address) {
+ conn->secondary_address = strdup(secondary_address);
+ }
+ return 0;
+}
+
+/*! \brief Free a msrcp_conn structure contents
+
+ This doesn't free the msrpc_conn object, but frees the contents.
+ */
+int
+MSRPC_FreeConn(msrpc_conn * conn)
+{
+ msrpc_call * call = NULL;
+
+ while(!MSRPC_GetCall(conn, &call)) {
+ MSRPC_FreeCall(call);
+ }
+
+ if (conn->secondary_address)
+ free(conn->secondary_address);
+
+ ZeroMemory(conn, sizeof(*conn));
+
+ return 0;
+}
+
+/*! \brief Write an RPC message into the RPC module
+
+ This function should be used by message mode RPC transports to
+ submit a single message. if successful, the message will be queued
+ for dispatch. The RPC will not be executed until
+ MSRPC_PrepareRead() or MSRPC_ReadMessageLength() or
+ MSRPC_ReadMessage() is called.
+ */
+int
+MSRPC_WriteMessage(msrpc_conn * conn, BYTE * buffer, unsigned int len,
+ cm_user_t * userp)
+{
+ msrpc_call * call;
+
+ if (len == 0)
+ return CM_ERROR_INVAL;
+
+ call = MSRPC_NewCall();
+
+ if (len > MAX_RPC_MSG_SIZE)
+ return CM_ERROR_BUFFERTOOSMALL;
+
+ MSRPC_AllocBuffer(&call->in, len);
+ memcpy(call->in.buf_data, buffer, len);
+ call->in.buf_pos = len;
+ call->in.buf_length = call->in.buf_pos;
+ call->status = MSRPC_CALL_MSGRECEIVED;
+
+ if (userp) {
+ call->cm_userp = userp;
+ cm_HoldUser(userp);
+ }
+
+ MSRPC_PutCall(conn, call);
+
+ return 0;
+}
+
+/*! \brief Prepare to read the next message from the RPC output queue
+
+ Each RPC message received is queued until the response is required.
+ MSRPC_PrepareRead() will, if necessary, dispatch the RPC request
+ and prepare the output buffer to be sent to the caller.
+ */
+int
+MSRPC_PrepareRead(msrpc_conn * conn)
+{
+ msrpc_call * call;
+ int code = 0;
+
+ while (conn->head) {
+ call = conn->head;
+
+ if (call->status == MSRPC_CALL_SKIP ||
+ call->status == MSRPC_CALL_MSGSENT ||
+ (call->status == MSRPC_CALL_DISPATCHED &&
+ call->out.buf_length == 0)) {
+
+ MSRPC_DequeueCall(conn, call);
+ MSRPC_FreeCall(call);
+ continue;
+ }
+
+ if (call->status == MSRPC_CALL_MSGRECEIVED) {
+ code = dispatch_call(conn);
+
+ /* If the dispatch failed, then we discard the message.
+ If the error was handled and a response packet was
+ created, dispatch_call() would return 0. */
+
+ if (code) {
+ MSRPC_DequeueCall(conn, call);
+ MSRPC_FreeCall(call);
+ }
+ continue;
+ }
+
+ break; /* the status wasn't SKIP or
+ MSGRECEIVED, or we successfully
+ dispatched the message. */
+ }
+
+ if (conn->head == NULL)
+ return CM_ERROR_BADFD;
+
+ if (conn->head->status == MSRPC_CALL_DISPATCHED ||
+ conn->head->status == MSRPC_CALL_MSGSENDING)
+ return 0;
+ else
+ return CM_ERROR_BADFD;
+}
+
+/*! \brief Return the size of the buffer for the next RPC message
+
+ Given the maximum size of the buffer, returns the actual size of
+ the data that will be copied. If the return value is 0, there is
+ no data to be sent to the caller either because there was no RPC
+ message queued or the queued message could not be dispatched.
+ */
+int
+MSRPC_ReadMessageLength(msrpc_conn * conn, unsigned int max_len)
+{
+ int code;
+ msrpc_call *call;
+
+ max_len = min(max_len, conn->max_recv_frag);
+
+ code = MSRPC_PrepareRead(conn);
+ if (code)
+ return 0;
+
+ call = conn->head;
+
+ if (call &&
+ (call->status == MSRPC_CALL_DISPATCHED ||
+ call->status == MSRPC_CALL_MSGSENDING)) {
+
+ switch(call->out.pdu_type) {
+ case PDU_TYPE_RESPONSE:
+ {
+ /* This calculation should mirror what
+ MSRPC_ReadMessage() does below. */
+
+ int fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
+ unsigned int len;
+
+ len = min(max_len, conn->max_recv_frag);
+
+ if (call->out.buf_pos % fragment_size == 0) {
+ if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD)
+ return 0;
+
+ len = min(len, RPC_RESPONSE_ENVELOPE_OVERHEAD + call->out.buf_length - call->out.buf_pos);
+ } else {
+ unsigned int to_copy;
+
+ to_copy = min(fragment_size - (call->out.buf_pos % fragment_size),
+ call->out.buf_length - call->out.buf_pos);
+ len = min(to_copy, len);
+ }
+
+ return len;
+ }
+
+ case PDU_TYPE_BIND_ACK:
+ case PDU_TYPE_FAULT:
+ case PDU_TYPE_BIND_NAK:
+ {
+ int len = min(call->out.buf_length - call->out.buf_pos, max_len);
+
+ return len;
+ }
+ }
+
+ return 0;
+ } else {
+ return 0;
+ }
+}
+
+/*! \brief Read the next message from the RPC queue
+
+ Copies the next chunk of data from the response buffer to the
+ buffer indicated by \a buffer and \a len.
+
+ \retval 0 The data was copied to the buffer. There is either no
+ more data to send or the existence of more data is implicit in
+ the data already sent. I.e. fragment flags were set
+ appropriately to indicate more data and we are at a fragment
+ boundary.
+
+ \retval CM_ERROR_RPC_MOREDATA The data was copied to the buffer and
+ there is more data to be sent.
+
+ \retval Else something went wrong. The data was not copied to the
+ buffer successfully.
+ */
+int
+MSRPC_ReadMessage(msrpc_conn * conn, BYTE *buffer, unsigned int len)
+{
+ int code;
+ msrpc_call * call;
+
+ code = MSRPC_PrepareRead(conn);
+ if (code)
+ return code;
+
+ if (conn->head &&
+ (conn->head->status == MSRPC_CALL_DISPATCHED ||
+ conn->head->status == MSRPC_CALL_MSGSENDING)) {
+
+ call = conn->head;
+
+ switch(call->out.pdu_type) {
+ case PDU_TYPE_RESPONSE:
+ {
+ BYTE * o_buffer = call->out.buf_data;
+ unsigned int o_alloc = call->out.buf_alloc;
+ unsigned int o_pos = call->out.buf_pos;
+ unsigned int o_len = call->out.buf_length;
+ unsigned int start_pos = o_pos;
+ unsigned int fragment_size;
+ fcursor o;
+
+ /* If call->out.buf_pos falls on a fragment boundary:
+
+ Assume that we are starting a new fragment and deal accordingly.
+
+ Else
+
+ Assume we are continuing a fragment.
+ */
+
+ fragment_size = conn->max_recv_frag - RPC_RESPONSE_ENVELOPE_OVERHEAD;
+
+ /* Don't send more than the max_recv_frag */
+ len = min(len, conn->max_recv_frag);
+
+ /* Switch the supplied user buffer with the output
+ buffer */
+ call->out.buf_data = buffer;
+ call->out.buf_length = 0;
+ call->out.buf_alloc = len;
+ call->out.buf_pos = 0;
+
+ if (o_pos % fragment_size == 0) {
+
+ /* New fragment:
+
+ We need to write the packet headers and
+ fragment bits here. The length of the buffer
+ should be at least big enough to hold the
+ entire envelope. We don't handle the case were
+ the envelope itself is too big.
+
+ */
+
+ if (len < RPC_RESPONSE_ENVELOPE_OVERHEAD) {
+ return CM_ERROR_INVAL;
+ }
+
+ code = write_E_CommonHeader(&o, conn, call, PDU_TYPE_RESPONSE);
+ if (code)
+ return code;
+
+ write_u_int32(&o, o_len); /* allocation hint */
+ write_u_int16(&o, call->context_id); /* presentation context ID */
+ write_u_int8(&o, 0); /* cancel count */
+ write_u_int8(&o, 0); /* reserved */
+
+ {
+ int to_copy = min(SPC_LEFT(&o), o_len - o_pos);
+ int rc;
+
+ O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
+
+ /* the fragment size of the message is the minimum of:
+
+ - max_recv_frag for the connection
+ - envelope size + (full message size - start offset)
+
+ */
+ rc = closeMessage(&o, call,
+ min(conn->max_recv_frag,
+ RPC_RESPONSE_ENVELOPE_OVERHEAD + o_len - start_pos));
+ if (rc)
+ return rc;
+
+ o_pos += to_copy;
+
+ /* If there is more data to be sent and we are
+ not at a fragment boundary after the last
+ send, we return CM_ERROR_RPC_MOREDATA.
+ Having more fragments to send is not a case
+ we indicate via a return value. */
+
+ if (o_pos < o_len &&
+ o_pos < start_pos + fragment_size)
+ code = CM_ERROR_RPC_MOREDATA;
+ }
+
+ if (start_pos + fragment_size < o_len)
+ buffer[3] &= ~PFC_LAST_FRAG;
+
+ if (start_pos != 0)
+ buffer[3] &= ~PFC_FIRST_FRAG;
+
+ } else {
+
+ /* Continuation:
+
+ The packet header should have already been sent
+ in a previous block.
+
+ */
+ unsigned int to_copy;
+
+ INITC(&o, call->out.buf_data, call->out.buf_alloc);
+
+ to_copy = min(fragment_size - (o_pos % fragment_size),
+ o_len - o_pos);
+ to_copy = min(to_copy, SPC_LEFT(&o));
+
+ O_WRITESZ(&o, (o_buffer + o_pos), to_copy);
+
+ o_pos += to_copy;
+
+ if (o_pos < o_len && (o_pos % fragment_size) != 0)
+ code = CM_ERROR_RPC_MOREDATA;
+ }
+
+ call->out.buf_data = o_buffer;
+ call->out.buf_alloc = o_alloc;
+ call->out.buf_pos = o_pos;
+ call->out.buf_length = o_len;
+
+ if (call->out.buf_pos < call->out.buf_length) {
+ call->status = MSRPC_CALL_MSGSENDING;
+ } else {
+ call->status = MSRPC_CALL_MSGSENT;
+ MSRPC_DequeueCall(conn, call);
+ MSRPC_FreeCall(call);
+ }
+ }
+ return code;
+
+ case PDU_TYPE_BIND_ACK:
+ case PDU_TYPE_FAULT:
+ case PDU_TYPE_BIND_NAK:
+ {
+ unsigned int to_send;
+
+ /* These types of packets are already fully formed.
+ We don't need to wrap them in an envelope. They
+ also don't fragment. */
+
+ to_send = call->out.buf_length - call->out.buf_pos;
+
+ if (len < to_send)
+ code = CM_ERROR_RPC_MOREDATA;
+ else
+ len = to_send;
+
+ if (len > 0) {
+ memcpy(buffer, call->out.buf_data + call->out.buf_pos, len);
+ }
+
+ call->out.buf_pos += len;
+
+ if (call->out.buf_pos < call->out.buf_length) {
+ call->status = MSRPC_CALL_MSGSENDING;
+ } else {
+ call->status = MSRPC_CALL_MSGSENT;
+ MSRPC_DequeueCall(conn, call);
+ MSRPC_FreeCall(call);
+ }
+ }
+ return code;
+ }
+
+ return CM_ERROR_INVAL;
+ } else {
+ return 0;
+ }
+}
+
+pthread_once_t msrpc_user_slot_init = PTHREAD_ONCE_INIT;
+
+DWORD msrpc_tls_user_slot = 0;
+
+static void
+msrpc_user_slot_init_func(void)
+{
+ msrpc_tls_user_slot = TlsAlloc();
+}
+
+cm_user_t *
+MSRPC_GetCmUser(void)
+{
+ pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
+
+ return (cm_user_t *) TlsGetValue(msrpc_tls_user_slot);
+}
+
+static void
+MSRPC_SetCmUser(cm_user_t * userp)
+{
+ pthread_once(&msrpc_user_slot_init, msrpc_user_slot_init_func);
+
+ TlsSetValue(msrpc_tls_user_slot, userp);
+}
+
+typedef struct I_RpcAllocatedBuffer {
+ DWORD magic; /* == _RPCALLOCATEDBUFFER_MAGIC */
+#define _RPCALLOCATEDBUFFER_MAGIC 0xa110ca73
+ struct I_RpcAllocatedBuffer * next;
+
+ /* Data goes here */
+} I_RpcAllocatedBuffer;
+
+#define I_RPCALLOCATEDBUFFER_FROM_PTR(v) (&(((I_RpcAllocatedBuffer *) (v))[-1]))
+
+RPC_STATUS
+RPC_ENTRY
+I_RpcGetBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
+{
+ I_RpcAllocatedBuffer * newBuffer = I_RpcAllocate(Message->BufferLength + sizeof(I_RpcAllocatedBuffer));
+ I_RpcAllocatedBuffer * oldBuffer = NULL;
+
+ if (Message->Buffer) {
+ oldBuffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
+ }
+
+ if (newBuffer) {
+ newBuffer->magic = _RPCALLOCATEDBUFFER_MAGIC;
+ newBuffer->next = oldBuffer;
+
+ Message->Buffer = &newBuffer[1];
+ } else {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ return RPC_S_OK;
+}
+
+RPC_STATUS
+RPC_ENTRY
+I_RpcFreeBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message)
+{
+ if (Message->Buffer) {
+ I_RpcAllocatedBuffer * buffer;
+
+ buffer = I_RPCALLOCATEDBUFFER_FROM_PTR(Message->Buffer);
+
+ while (buffer) {
+ I_RpcAllocatedBuffer * bnext;
+
+ bnext = buffer->next;
+
+ I_RpcFree(buffer);
+
+ buffer = bnext;
+ }
+
+ Message->Buffer = NULL;
+ }
+
+ return RPC_S_OK;
+}
+
+unsigned char *
+RPC_ENTRY
+NdrServerInitializeNew(
+ PRPC_MESSAGE pRpcMsg,
+ PMIDL_STUB_MESSAGE pStubMsg,
+ PMIDL_STUB_DESC pStubDesc
+ )
+{
+ ZeroMemory(pStubMsg, sizeof(*pStubMsg));
+
+ pStubMsg->RpcMsg = pRpcMsg;
+ pStubMsg->Buffer = pRpcMsg->Buffer;
+ pStubMsg->BufferStart = pRpcMsg->Buffer;
+ pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
+ pStubMsg->BufferLength = pRpcMsg->BufferLength;
+ pStubMsg->MemorySize = pRpcMsg->BufferLength;
+ pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
+ pStubMsg->pfnFree = pStubDesc->pfnFree;
+ pStubMsg->StubDesc = pStubDesc;
+ pStubMsg->dwDestContext = MSHCTX_LOCAL;
+
+ return NULL;
+}
+
+void
+MSRPC_Init(void) {
+ RPC_SRVSVC_Init();
+}
+
+void
+MSRPC_Shutdown(void) {
+ RPC_SRVSVC_Shutdown();
+}
--- /dev/null
+/*
+ * Copyright (c) 2009 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#pragma once
+
+#include <Rpc.h>
+#include <RpcdceP.h>
+#include <RpcNdr.h>
+
+#define I_RpcGetBuffer MSRPC_I_GetBuffer
+
+#define I_RpcFreeBuffer MSRPC_I_FreeBuffer
+
+#define NdrServerInitializeNew MSRPC_NdrServerInitializeNew
+
+/*! \brief Maximum size of an accepted message
+
+ This value is arbitrary. The chosen value is larger than the
+ maximum fragment size used by the SMB RPC transport and is only
+ meant to mitigate the damage that could be done from a malformed
+ packet.
+ */
+#define MAX_RPC_MSG_SIZE 102400
+
+/*! \brief Default message size */
+#define DEF_RPC_MSG_SIZE 2048
+
+/*! \brief Status of a msrpc_call object */
+typedef enum msrpc_call_status {
+ MSRPC_CALL_NONE = 0,
+ MSRPC_CALL_MSGRECEIVED,
+ MSRPC_CALL_DISPATCHED,
+ MSRPC_CALL_MSGSENDING,
+ MSRPC_CALL_MSGSENT,
+ MSRPC_CALL_SKIP,
+} MSRPC_CALL_STATUS;
+
+typedef enum PDU_type {
+ PDU_TYPE_REQUEST = 0,
+ PDU_TYPE_PING = 1,
+ PDU_TYPE_RESPONSE = 2,
+ PDU_TYPE_FAULT = 3,
+ PDU_TYPE_WORKING = 4,
+ PDU_TYPE_NOCALL = 5,
+ PDU_TYPE_REJECT = 6,
+ PDU_TYPE_ACK = 7,
+ PDU_TYPE_CL_CANCEL = 8,
+ PDU_TYPE_FACK = 9,
+ PDU_TYPE_CANCEL_ACK = 10,
+ PDU_TYPE_BIND = 11,
+ PDU_TYPE_BIND_ACK = 12,
+ PDU_TYPE_BIND_NAK = 13,
+ PDU_TYPE_ALTER_CONTEXT = 14,
+ PDU_TYPE_ALTER_CONTEXT_RESP = 15,
+ PDU_TYPE_SHUTDOWN = 16,
+ PDU_TYPE_CO_CANCEL = 18,
+ PDU_TYPE_ORPHANED = 19
+} PDU_TYPE;
+
+typedef enum msrpc_bind_reject_reason {
+ BIND_REJ_REASON_NOT_SPECIFIED = 0,
+ BIND_REJ_TEMPORARY_CONGESTION = 1,
+ BIND_REJ_LOCAL_LIMIT_EXCEEDED = 2,
+ BIND_REJ_CALLED_PADDR_UNKNOWN = 3, /* not used */
+ BIND_REJ_PROTOCOL_VERSION_NOT_SUPPORTED = 4,
+ BIND_REJ_DEFAULT_CONTEXT_NOT_SUPPORTED = 5, /* not used */
+ BIND_REJ_USER_DATA_NOT_READABLE = 6, /* not used */
+ BIND_REJ_NO_PSAP_AVAILABLE = 7 /* not used */
+} BIND_REJECT_REASON;
+
+typedef unsigned __int8 byte;
+typedef unsigned __int8 u_int8;
+typedef unsigned __int16 u_int16;
+typedef unsigned __int32 u_int32;
+typedef unsigned __int64 u_int64;
+
+/*! \brief Common RPC envelope header */
+typedef
+struct E_CommonHeader {
+ u_int8 rpc_vers; /*!< 00:01 RPC version == 5 */
+ u_int8 rpc_vers_minor; /*!< 01:01 minor version */
+ u_int8 PTYPE; /*!< 02:01 packet type */
+ u_int8 pfc_flags; /*!< 03:01 flags (see PFC_... ) */
+
+#define PFC_FIRST_FRAG 0x01 /* First fragment */
+#define PFC_LAST_FRAG 0x02 /* Last fragment */
+#define PFC_PENDING_CANCEL 0x04 /* Cancel was pending at sender */
+#define PFC_RESERVED_1 0x08
+#define PFC_CONC_MPX 0x10 /* supports concurrent multiplexing
+ * of a single connection. */
+#define PFC_DID_NOT_EXECUTE 0x20 /* only meaningful on `fault' packet;
+ * if true, guaranteed call did not
+ * execute. */
+#define PFC_MAYBE 0x40 /* `maybe' call semantics requested */
+#define PFC_OBJECT_UUID 0x80 /* if true, a non-nil object UUID
+ * was specified in the handle, and
+ * is present in the optional object
+ * field. If false, the object field
+ * is omitted. */
+
+ byte packed_drep[4]; /*!< 04:04 NDR data representation format label */
+ u_int16 frag_length; /*!< 08:02 total length of fragment */
+ u_int16 auth_length; /*!< 10:02 length of auth_value */
+ u_int32 call_id; /*!< 12:04 call identifier */
+} E_CommonHeader;
+
+typedef u_int16 p_context_id_t; /* local context identifier */
+
+/*! \brief RPC message buffer
+ */
+typedef struct msrpc_buffer {
+ BYTE * buf_data;
+ unsigned int buf_length;
+ unsigned int buf_alloc;
+ unsigned int buf_pos;
+
+ PDU_TYPE pdu_type;
+} msrpc_buffer;
+
+typedef struct cm_user cm_user_t;
+
+/*! \brief RPC call
+
+ A single RPC call. This might even be a single fragment of a
+ message.
+ */
+typedef struct msrpc_call {
+ struct msrpc_call * next;
+ struct msrpc_call * prev;
+
+ MSRPC_CALL_STATUS status;
+
+ u_int32 call_id; /*!< Call ID */
+ p_context_id_t context_id; /*!< presentation context ID (last seen) */
+
+ E_CommonHeader * in_header; /*!< Pointer to the header of the
+ input packet. Only valid during a
+ request dispatch. */
+
+ msrpc_buffer in; /*!< Input buffer */
+
+ msrpc_buffer out; /*!< Output buffer */
+
+ RPC_MESSAGE msg;
+
+ cm_user_t *cm_userp; /*!< Held reference to the cm_user_t
+ associated with this call. */
+} msrpc_call;
+
+/*! \brief RPC connection structure
+
+ Represents a single RPC connection. Can support multiple queued
+ RPCs.
+*/
+typedef struct _msrpc_conn {
+ unsigned int max_xmit_frag; /*!< Maximum size of fragment
+ client->server */
+ unsigned int max_recv_frag; /*!< Maximum size of fragment
+ server->client */
+ u_int32 assoc_group_id; /*!< Association group ID for the
+ connection. */
+
+ unsigned int rpc_vers; /*!< RPC Protocol version. Always 5 */
+ unsigned int rpc_vers_minor; /*!< Minor version number. 0 or 1 */
+
+ char * secondary_address; /*!< Secondary address for the
+ connection. */
+
+ RPC_SERVER_INTERFACE * interface;
+ /*!< Selected server interface. Only
+ valid after a successful bind. */
+
+ msrpc_call * head; /*!< Queue of msrpc_call objects for
+ the connection. */
+ msrpc_call * tail;
+} msrpc_conn;
+
+
+void
+MSRPC_Init(void);
+
+void
+MSRPC_Shutdown(void);
+
+int
+MSRPC_InitConn(msrpc_conn * conn, const char * secondary_address);
+
+int
+MSRPC_FreeConn(msrpc_conn * conn);
+
+int
+MSRPC_WriteMessage(msrpc_conn * conn, BYTE * buffer, unsigned int len,
+ cm_user_t * userp);
+
+int
+MSRPC_PrepareRead(msrpc_conn * conn);
+
+int
+MSRPC_ReadMessageLength(msrpc_conn * conn, unsigned int max_len);
+
+int
+MSRPC_ReadMessage(msrpc_conn * conn, BYTE *buffer, unsigned int len);
+
+RPC_STATUS
+RPC_ENTRY
+I_RpcGetBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message);
+
+RPC_STATUS
+RPC_ENTRY
+I_RpcFreeBuffer (IN OUT RPC_MESSAGE __RPC_FAR * Message);
+
+unsigned char *
+RPC_ENTRY
+NdrServerInitializeNew(
+ PRPC_MESSAGE pRpcMsg,
+ PMIDL_STUB_MESSAGE pStubMsg,
+ PMIDL_STUB_DESC pStubDescriptor
+ );
+
+extern cm_user_t *
+MSRPC_GetCmUser(void);
+
+extern void RPC_SRVSVC_Init(void);
+
+extern void RPC_SRVSVC_Shutdown(void);
+
--- /dev/null
+/*
+ * Copyright (c) 2009 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include<windows.h>
+#include <wchar.h>
+#define _CRT_RAND_S
+#include <stdlib.h>
+#include <strsafe.h>
+#include <svrapi.h>
+#include "ms-srvsvc.h"
+#include "msrpc.h"
+#include "afsd.h"
+#include <WINNT/afsreg.h>
+#define AFS_VERSION_STRINGS
+#include "AFS_component_version_number.h"
+
+#pragma warning( disable: 4027 ) /* func w/o formal parameter list */
+
+/* Do not pull in lmserver.h */
+//
+// The platform ID indicates the levels to use for platform-specific
+// information.
+//
+#define SV_PLATFORM_ID_DOS 300
+#define SV_PLATFORM_ID_OS2 400
+#define SV_PLATFORM_ID_NT 500
+#define SV_PLATFORM_ID_OSF 600
+#define SV_PLATFORM_ID_VMS 700
+#define SV_PLATFORM_ID_AFS 800
+//
+// Bit-mapped values for svX_type fields. X = 1, 2 or 3.
+//
+#define SV_TYPE_WORKSTATION 0x00000001
+#define SV_TYPE_SERVER 0x00000002
+#define SV_TYPE_SQLSERVER 0x00000004
+#define SV_TYPE_DOMAIN_CTRL 0x00000008
+#define SV_TYPE_DOMAIN_BAKCTRL 0x00000010
+#define SV_TYPE_TIME_SOURCE 0x00000020
+#define SV_TYPE_AFP 0x00000040
+#define SV_TYPE_NOVELL 0x00000080
+#define SV_TYPE_DOMAIN_MEMBER 0x00000100
+#define SV_TYPE_PRINTQ_SERVER 0x00000200
+#define SV_TYPE_DIALIN_SERVER 0x00000400
+#define SV_TYPE_XENIX_SERVER 0x00000800
+#define SV_TYPE_SERVER_UNIX SV_TYPE_XENIX_SERVER
+#define SV_TYPE_NT 0x00001000
+#define SV_TYPE_WFW 0x00002000
+#define SV_TYPE_SERVER_MFPN 0x00004000
+#define SV_TYPE_SERVER_NT 0x00008000
+#define SV_TYPE_POTENTIAL_BROWSER 0x00010000
+#define SV_TYPE_BACKUP_BROWSER 0x00020000
+#define SV_TYPE_MASTER_BROWSER 0x00040000
+#define SV_TYPE_DOMAIN_MASTER 0x00080000
+#define SV_TYPE_SERVER_OSF 0x00100000
+#define SV_TYPE_SERVER_VMS 0x00200000
+#define SV_TYPE_WINDOWS 0x00400000 /* Windows95 and above */
+#define SV_TYPE_DFS 0x00800000 /* Root of a DFS tree */
+#define SV_TYPE_CLUSTER_NT 0x01000000 /* NT Cluster */
+#define SV_TYPE_TERMINALSERVER 0x02000000 /* Terminal Server(Hydra) */
+#define SV_TYPE_CLUSTER_VS_NT 0x04000000 /* NT Cluster Virtual Server Name */
+#define SV_TYPE_DCE 0x10000000 /* IBM DSS (Directory and Security Services) or equivalent */
+#define SV_TYPE_ALTERNATE_XPORT 0x20000000 /* return list for alternate transport */
+#define SV_TYPE_LOCAL_LIST_ONLY 0x40000000 /* Return local list only */
+#define SV_TYPE_DOMAIN_ENUM 0x80000000
+#define SV_TYPE_ALL 0xFFFFFFFF /* handy for NetServerEnum2 */
+//
+// Values of svX_hidden field. X = 2 or 3.
+//
+#define SV_HIDDEN 1
+#define SV_VISIBLE 0
+
+NET_API_STATUS NetrConnectionEnum(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [unique][string][in] */ WCHAR *Qualifier,
+ /* [out][in] */ LPCONNECT_ENUM_STRUCT InfoStruct,
+ /* [in] */ DWORD PreferedMaximumLength,
+ /* [out] */ DWORD *TotalEntries,
+ /* [unique][out][in] */ DWORD *ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrFileEnum(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [unique][string][in] */ WCHAR *BasePath,
+ /* [unique][string][in] */ WCHAR *UserName,
+ /* [out][in] */ PFILE_ENUM_STRUCT InfoStruct,
+ /* [in] */ DWORD PreferedMaximumLength,
+ /* [out] */ DWORD *TotalEntries,
+ /* [unique][out][in] */ DWORD *ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrFileGetInfo(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD FileId,
+ /* [in] */ DWORD Level,
+ /* [switch_is][out] */ LPFILE_INFO InfoStruct)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrFileClose(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD FileId)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrSessionEnum(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [unique][string][in] */ WCHAR *ClientName,
+ /* [unique][string][in] */ WCHAR *UserName,
+ /* [out][in] */ PSESSION_ENUM_STRUCT InfoStruct,
+ /* [in] */ DWORD PreferedMaximumLength,
+ /* [out] */ DWORD *TotalEntries,
+ /* [unique][out][in] */ DWORD *ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrSessionDel(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [unique][string][in] */ WCHAR *ClientName,
+ /* [unique][string][in] */ WCHAR *UserName)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrShareAdd(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][in] */ LPSHARE_INFO InfoStruct,
+ /* [unique][out][in] */ DWORD *ParmErr)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+static wchar_t *
+NetrIntGenerateShareRemark(cm_scache_t *scp, cm_fid_t *fidp)
+{
+ wchar_t remark[1536], *s, *wcellname, *wmp;
+ HRESULT hr;
+ cm_cell_t *cellp;
+ afs_int32 b;
+
+ cellp = cm_FindCellByID(fidp->cell, CM_FLAG_NOPROBE);
+
+ if (cellp)
+ wcellname = cm_FsStringToClientStringAlloc(cellp->name, -1, NULL);
+ else
+ wcellname = L"";
+
+ if (scp) {
+ switch (scp->fileType) {
+ case 1:
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"AFS File (%s:%u.%u.%u)",
+ wcellname,
+ scp->fid.volume,
+ scp->fid.vnode, scp->fid.unique);
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"AFS File");
+ break;
+ case 2:
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"AFS Directory (%s:%u.%u.%u)",
+ wcellname,
+ scp->fid.volume,
+ scp->fid.vnode, scp->fid.unique);
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"AFS Directory");
+ break;
+ case 3:
+ wmp = cm_FsStringToClientStringAlloc(scp->mountPointStringp, -1, NULL);
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"AFS Symlink to %s",
+ wmp ? wmp : L"");
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"AFS Symlink");
+ if (wmp)
+ free(wmp);
+ break;
+ case 4:
+ b = (strchr(scp->mountPointStringp, ':') != NULL);
+ wmp = cm_FsStringToClientStringAlloc(scp->mountPointStringp, -1, NULL);
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"AFS MountPoint to %s%s%s%s",
+ wmp ? wmp : L"",
+ b ? L"" : L" (",
+ b ? L"" : wcellname,
+ b ? L"" : L")");
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"AFS MountPoint");
+ if (wmp)
+ free(wmp);
+ break;
+ case 5:
+ wmp = cm_FsStringToClientStringAlloc(scp->mountPointStringp, -1, NULL);
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"AFS Dfslink to %s",
+ wmp ? wmp : L"");
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"AFS DfsLink");
+ if (wmp)
+ free(wmp);
+ break;
+ default:
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"AFS Object (%s:%u.%u.%u)",
+ wcellname,
+ scp->fid.volume,
+ scp->fid.vnode, scp->fid.unique);
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"AFS Object");
+ }
+ } else {
+ if (fidp->vnode & 1) {
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"AFS Directory (%s:%u.%u.%u)",
+ wcellname,
+ fidp->volume,
+ fidp->vnode, fidp->unique);
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"AFS Directory");
+ } else {
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"AFS Object (%s:%u.%u.%u)",
+ wcellname,
+ fidp->volume,
+ fidp->vnode, fidp->unique);
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"AFS Object");
+ }
+ }
+ if (cellp && wcellname)
+ free(wcellname);
+ return s;
+}
+
+static wchar_t *
+NetrIntGenerateSharePath(wchar_t *ServerName, cm_fid_t *fidp)
+{
+ wchar_t remark[1536], *s, *wcellname;
+ HRESULT hr;
+ cm_cell_t *cellp;
+
+ cellp = cm_FindCellByID(fidp->cell, CM_FLAG_NOPROBE);
+
+ if (cellp)
+ wcellname = cm_FsStringToClientStringAlloc(cellp->name, -1, NULL);
+ else
+ wcellname = L"";
+
+ hr = StringCchPrintfW( remark,
+ sizeof(remark)/sizeof(remark[0]),
+ L"\\%s\\%s\\%u.%u.%u",
+ ServerName, wcellname,
+ fidp->volume,
+ fidp->vnode, fidp->unique);
+ if (hr == S_OK)
+ s = wcsdup(remark);
+ else
+ s = wcsdup(L"");
+
+ if (cellp && wcellname)
+ free(wcellname);
+ return s;
+}
+
+typedef struct netr_share_enum {
+ osi_queue_t q;
+ time_t cleanup_time;
+ DWORD handle;
+ cm_direnum_t *direnump;
+} netr_share_enum_t;
+
+static osi_queue_t * shareEnumQ = NULL;
+static osi_mutex_t shareEnum_mx;
+static DWORD shareEnum_next_handle=1;
+
+void
+RPC_SRVSVC_Init(void)
+{
+ lock_InitializeMutex(&shareEnum_mx, "NetrShareEnum", 0);
+ shareEnumQ = NULL;
+ rand_s(&shareEnum_next_handle);
+}
+
+void
+RPC_SRVSVC_Shutdown(void)
+{
+ netr_share_enum_t *enump;
+
+ lock_ObtainMutex(&shareEnum_mx);
+ while (shareEnumQ) {
+ enump = (netr_share_enum_t *)shareEnumQ;
+ cm_BPlusDirFreeEnumeration(enump->direnump);
+ osi_QRemove(&shareEnumQ, (osi_queue_t *)enump);
+ free(enump);
+ }
+ lock_FinalizeMutex(&shareEnum_mx);
+}
+
+static void
+RPC_SRVSVC_ShareEnumAgeCheck(void) {
+ netr_share_enum_t *enump, *enumnp;
+ time_t now;
+
+ lock_ObtainMutex(&shareEnum_mx);
+ now = time(NULL);
+ for (enump = (netr_share_enum_t *)shareEnumQ;
+ enump; enump = enumnp) {
+ enumnp = (netr_share_enum_t *) osi_QNext(&(enump->q));
+ if (now > enump->cleanup_time)
+ osi_QRemove(&shareEnumQ, (osi_queue_t *)enump);
+ }
+ lock_ReleaseMutex(&shareEnum_mx);
+}
+
+static cm_direnum_t *
+RPC_SRVSVC_ShareEnumFind(DWORD ResumeHandle) {
+ netr_share_enum_t *enump;
+
+ lock_ObtainMutex(&shareEnum_mx);
+ for (enump = (netr_share_enum_t *)shareEnumQ;
+ enump;
+ enump = (netr_share_enum_t *) osi_QNext(&enump->q)) {
+ if (ResumeHandle == enump->handle)
+ break;
+ }
+ lock_ReleaseMutex(&shareEnum_mx);
+
+ return enump ? enump->direnump : NULL;
+}
+
+static DWORD
+RPC_SRVSVC_ShareEnumSave(cm_direnum_t *direnump) {
+ netr_share_enum_t *enump = (netr_share_enum_t *)malloc(sizeof(netr_share_enum_t));
+
+ if (enump == NULL)
+ return 0xFFFFFFFF;
+
+ lock_ObtainMutex(&shareEnum_mx);
+ enump->cleanup_time = time(NULL) + 300;
+ enump->handle = shareEnum_next_handle++;
+ if (shareEnum_next_handle == 0xFFFFFFFF)
+ shareEnum_next_handle = 1;
+ enump->direnump = direnump;
+ osi_QAdd(&shareEnumQ, (osi_queue_t *)enump);
+ lock_ReleaseMutex(&shareEnum_mx);
+
+ return enump->handle;
+}
+
+static void
+RPC_SRVSVC_ShareEnumRemove(cm_direnum_t *direnump) {
+ netr_share_enum_t *enump;
+
+ lock_ObtainMutex(&shareEnum_mx);
+ for (enump = (netr_share_enum_t *)shareEnumQ;
+ enump;
+ enump = (netr_share_enum_t *) osi_QNext(&enump->q)) {
+ if (direnump == enump->direnump) {
+ osi_QRemove(&shareEnumQ, (osi_queue_t *)enump);
+ break;
+ }
+ }
+ lock_ReleaseMutex(&shareEnum_mx);
+}
+
+NET_API_STATUS NetrShareEnum(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [out][in] */ LPSHARE_ENUM_STRUCT InfoStruct,
+ /* [in] */ DWORD PreferedMaximumLength,
+ /* [out] */ DWORD *TotalEntries,
+ /* [unique][out][in] */ DWORD *ResumeHandle)
+{
+ cm_direnum_t *enump = NULL;
+ cm_direnum_entry_t * entryp = NULL;
+ cm_scache_t * dscp = cm_data.rootSCachep;
+ cm_user_t *userp = MSRPC_GetCmUser();
+ cm_req_t req;
+ int stopnow = 0;
+ afs_uint32 count = 0;
+ afs_uint32 code;
+ afs_uint32 old_enum = 0;
+ size_t space_limited = 0;
+ size_t space_available = 0;
+ afs_uint32 first_entry = 1;
+
+ cm_InitReq(&req);
+
+ RPC_SRVSVC_ShareEnumAgeCheck();
+
+ /* We only support one server name so ignore 'ServerName'. */
+
+ /* Test for unsupported level early */
+ switch (InfoStruct->Level) {
+ case 2:
+ case 1:
+ case 0:
+ break;
+ default:
+ return ERROR_INVALID_LEVEL;
+ }
+
+ if (ResumeHandle && *ResumeHandle == 0xFFFFFFFF) {
+ /* No More Entries */
+ InfoStruct->ShareInfo.Level0->EntriesRead = 0;
+ return ERROR_NO_MORE_FILES;
+ }
+
+ /* get the directory size */
+ cm_HoldSCache(dscp);
+ lock_ObtainWrite(&dscp->rw);
+ code = cm_SyncOp(dscp, NULL, userp, &req, PRSFS_LOOKUP,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code) {
+ lock_ReleaseWrite(&dscp->rw);
+ cm_ReleaseSCache(dscp);
+ osi_Log1(afsd_logp, "NetShareEnum cm_SyncOp failure code=0x%x", code);
+ return ERROR_BUSY;
+ }
+
+ cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&dscp->rw);
+
+ if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
+ cm_ReleaseSCache(dscp);
+ osi_Log1(afsd_logp, "NetShareEnum Not a Directory dscp=0x%p", dscp);
+ return ERROR_DIRECTORY;
+ }
+
+ /*
+ * If there is no enumeration handle, then this is a new query
+ * and we must perform an enumeration for the specified object
+ */
+ if (ResumeHandle == NULL || *ResumeHandle == 0) {
+ cm_dirOp_t dirop;
+
+ code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, &dirop);
+ if (code == 0) {
+ code = cm_BPlusDirEnumerate(dscp, userp, &req, TRUE, NULL, TRUE, &enump);
+ if (code) {
+ osi_Log1(afsd_logp, "NetShareEnum cm_BPlusDirEnumerate failure code=0x%x",
+ code);
+ }
+ cm_EndDirOp(&dirop);
+ } else {
+ osi_Log1(afsd_logp, "NetShareEnum cm_BeginDirOp failure code=0x%x",
+ code);
+ }
+ old_enum = 0;
+ } else {
+ enump = RPC_SRVSVC_ShareEnumFind(*ResumeHandle);
+ old_enum = 1;
+ }
+
+ if (enump == NULL) {
+ cm_ReleaseSCache(dscp);
+ osi_Log0(afsd_logp, "NetShareEnum No Enumeration Present");
+ *TotalEntries = 0;
+ return (code ? ERROR_BUSY : ERROR_SUCCESS);
+ }
+
+ /*
+ * Do not exceed PreferredMaximumLength in any response.
+ * 0xFFFFFFFF means no limit.
+ *
+ * *TotalEntries is a hint of the total entries in the
+ * enumeration. It does not have to be exact. It is
+ * the same for each response in an enum.
+ *
+ * If *ResumeHandle == 0, this is an initial call
+ *
+ * The algorithm will be to enumerate the list of share
+ * names based upon the contents of the root.afs root
+ * directory. We will ignore SMB submount names.
+ * The enumeration will be valid for five minutes. If
+ * the enumeration is not destroyed within that time period
+ * it will be automatically garbage collected.
+ */
+
+ /*
+ * How much space do we need and do we have that much room?
+ *
+ * If a preferred maximum length is specified, then we must
+ * manage the number of bytes we return in order to restrict
+ * it to a value smaller than then the preferred. This includes
+ * not only the InfoStruct but also the allocated SHARE_INFO
+ * buffer and the various C strings. We are not permitted to
+ * send incomplete values so we will send a value that is close.
+ */
+ if (PreferedMaximumLength != 0xFFFFFFFF) {
+ space_limited = 1;
+ space_available = PreferedMaximumLength;
+ }
+
+ switch (InfoStruct->Level) {
+ case 2:
+ if (space_limited)
+ space_available -= sizeof(InfoStruct->ShareInfo.Level2);
+ InfoStruct->ShareInfo.Level2->Buffer = calloc((enump->count - enump->next), sizeof(SHARE_INFO_2));
+ break;
+ case 1:
+ if (space_limited)
+ space_available -= sizeof(InfoStruct->ShareInfo.Level1);
+ InfoStruct->ShareInfo.Level1->Buffer = calloc((enump->count - enump->next), sizeof(SHARE_INFO_1));
+ break;
+ case 0:
+ if (space_limited)
+ space_available -= sizeof(InfoStruct->ShareInfo.Level0);
+ InfoStruct->ShareInfo.Level0->Buffer = calloc((enump->count - enump->next), sizeof(SHARE_INFO_0));
+ break;
+ }
+
+ if (InfoStruct->ShareInfo.Level0->Buffer == NULL) {
+ cm_ReleaseSCache(dscp);
+ cm_BPlusDirFreeEnumeration(enump);
+ osi_Log0(afsd_logp, "NetShareEnum No Enumeration Present");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ while (!stopnow) {
+ cm_scache_t *scp;
+
+ if (space_limited)
+ code = cm_BPlusDirPeekNextEnumEntry(enump, &entryp);
+ else
+ code = cm_BPlusDirNextEnumEntry(enump, &entryp);
+ if (code != 0 && code != CM_ERROR_STOPNOW || entryp == NULL)
+ break;
+
+ stopnow = (code == CM_ERROR_STOPNOW);
+
+ if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
+ osi_Log0(afsd_logp, "NetShareEnum skipping . or ..");
+ if (space_limited)
+ cm_BPlusDirNextEnumEntry(enump, &entryp);
+ continue;
+ }
+
+ cm_GetSCache(&entryp->fid, &scp, userp, &req);
+
+ switch (InfoStruct->Level) {
+ case 2:
+ /* for share level security */
+ InfoStruct->ShareInfo.Level2->Buffer[count].shi2_permissions = 0;
+ InfoStruct->ShareInfo.Level2->Buffer[count].shi2_max_uses = -1;
+ InfoStruct->ShareInfo.Level2->Buffer[count].shi2_current_uses = 0;
+ InfoStruct->ShareInfo.Level2->Buffer[count].shi2_path =
+ NetrIntGenerateSharePath(ServerName, &entryp->fid);
+ /* must be the empty string */
+ InfoStruct->ShareInfo.Level2->Buffer[count].shi2_passwd = wcsdup(L"");
+
+ InfoStruct->ShareInfo.Level2->Buffer[count].shi2_type = STYPE_DISKTREE;
+ InfoStruct->ShareInfo.Level2->Buffer[count].shi2_remark =
+ NetrIntGenerateShareRemark(scp, &entryp->fid);
+ InfoStruct->ShareInfo.Level2->Buffer[count].shi2_netname = wcsdup(entryp->name);
+ break;
+ case 1:
+ InfoStruct->ShareInfo.Level1->Buffer[count].shi1_type = STYPE_DISKTREE;
+ InfoStruct->ShareInfo.Level1->Buffer[count].shi1_remark =
+ NetrIntGenerateShareRemark(scp, &entryp->fid);
+ InfoStruct->ShareInfo.Level1->Buffer[count].shi1_netname = wcsdup(entryp->name);
+ break;
+ case 0:
+ InfoStruct->ShareInfo.Level0->Buffer[count].shi0_netname = wcsdup(entryp->name);
+ }
+
+ if (scp)
+ cm_ReleaseSCache(scp);
+
+ if (space_limited) {
+ size_t space_used;
+ /*
+ * If space is limited, we need to determine if there is room
+ * for the next entry but always send at least one.
+ */
+ switch (InfoStruct->Level) {
+ case 2:
+ space_used = sizeof(InfoStruct->ShareInfo.Level2->Buffer[count]) +
+ (wcslen(InfoStruct->ShareInfo.Level2->Buffer[count].shi2_path) + 1) * sizeof(wchar_t) +
+ sizeof(wchar_t) + /* passwd */
+ (wcslen(InfoStruct->ShareInfo.Level2->Buffer[count].shi2_remark) + 1) * sizeof(wchar_t) +
+ (wcslen(InfoStruct->ShareInfo.Level2->Buffer[count].shi2_netname) + 1) * sizeof(wchar_t);
+ break;
+ case 1:
+ space_used = sizeof(InfoStruct->ShareInfo.Level1->Buffer[count]) +
+ (wcslen(InfoStruct->ShareInfo.Level1->Buffer[count].shi1_remark) + 1) * sizeof(wchar_t) +
+ (wcslen(InfoStruct->ShareInfo.Level1->Buffer[count].shi1_netname) + 1) * sizeof(wchar_t);
+ break;
+ case 0:
+ space_used = sizeof(InfoStruct->ShareInfo.Level0->Buffer[count]) +
+ (wcslen(InfoStruct->ShareInfo.Level0->Buffer[count].shi0_netname) + 1) * sizeof(wchar_t);
+ break;
+ }
+
+ if (!first_entry && space_used > space_available)
+ break;
+
+ /* Now consume the entry */
+ cm_BPlusDirNextEnumEntry(enump, &entryp);
+ space_available -= space_used;
+ }
+ count++;
+ first_entry = 0;
+ }
+ InfoStruct->ShareInfo.Level0->EntriesRead = count;
+ *TotalEntries = enump->count;
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+
+ if (code || enump->next == enump->count || ResumeHandle == NULL) {
+ if (old_enum)
+ RPC_SRVSVC_ShareEnumRemove(enump);
+ cm_BPlusDirFreeEnumeration(enump);
+ if (ResumeHandle)
+ *ResumeHandle = 0xFFFFFFFF;
+ return (code || enump->next == enump->count) ? 0 : ERROR_MORE_DATA;
+ } else {
+ *ResumeHandle = RPC_SRVSVC_ShareEnumSave(enump);
+ return ERROR_MORE_DATA;
+ }
+}
+
+NET_API_STATUS NetrShareGetInfo(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *NetName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][out] */ LPSHARE_INFO InfoStruct)
+{
+ cm_scache_t * dscp = cm_data.rootSCachep;
+ cm_scache_t * scp = NULL;
+ cm_user_t *userp = MSRPC_GetCmUser();
+ cm_req_t req;
+ afs_uint32 code = 0;
+ NET_API_STATUS status = 0;
+ HKEY parmKey;
+ /* make room for '/@vol:' + mountchar + NULL terminator*/
+ clientchar_t pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH];
+ DWORD cblen;
+
+ cm_InitReq(&req);
+
+ /* Allocate the memory for the response */
+ switch (Level) {
+ case 2:
+ InfoStruct->ShareInfo2 = calloc(1, sizeof(SHARE_INFO_2));
+ break;
+ case 1:
+ InfoStruct->ShareInfo1 = calloc(1, sizeof(SHARE_INFO_1));
+ break;
+ case 0:
+ InfoStruct->ShareInfo0 = calloc(1, sizeof(SHARE_INFO_0));
+ break;
+ }
+
+ if (InfoStruct->ShareInfo0 == NULL) {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /*
+ * NetName will be:
+ * 1.a an entry in the root.afs volume root directory
+ * 1.b an entry in the Freelance volume root directory
+ * 2. A volume reference: <cell><type><volume>
+ * 3. an SMB Submount name
+ * 4. a cell name that we do not yet have an entry
+ * for in the Freelance volume root directory
+ */
+
+ /*
+ * To obtain the needed information for the response we
+ * need to obtain the cm_scache_t entry. First check to
+ * see if the NetName is a volume reference, then check
+ * if the NetName is an entry in the root volume root
+ * directory, finally we can check the SMB Submounts.
+ * Volume references and SMB submounts are not advertised
+ * as part of the Share enumerations but we should provide
+ * Share info for them nevertheless. Same for the secret
+ * "all" share.
+ */
+
+ /* Check for volume references
+ *
+ * They look like <cell>{%,#}<volume>
+ */
+ if (cm_ClientStrChr(NetName, '%') != NULL ||
+ cm_ClientStrChr(NetName, '#') != NULL)
+ {
+ osi_Log1(afsd_logp, "NetrShareGetInfo found volume reference [%S]",
+ osi_LogSaveClientString(afsd_logp, NetName));
+
+ cm_ClientStrPrintfN(pathstr, lengthof(pathstr),
+ _C(CM_PREFIX_VOL) _C("%s"), NetName);
+ code = cm_Lookup(dscp, pathstr, 0, userp, &req, &scp);
+ } else if (cm_ClientStrCmpI(NetName, L"ALL") == 0) {
+ DWORD allSubmount = 1;
+
+ /* if allSubmounts == 0, only return the //mountRoot/all share
+ * if in fact it has been been created in the subMounts table.
+ * This is to allow sites that want to restrict access to the
+ * world to do so.
+ */
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ cblen = sizeof(allSubmount);
+ code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
+ (BYTE *) &allSubmount, &cblen);
+ if (code != ERROR_SUCCESS) {
+ allSubmount = 1;
+ }
+ RegCloseKey (parmKey);
+ }
+
+ if (allSubmount) {
+ scp = dscp;
+ cm_HoldSCache(scp);
+ }
+ } else {
+ /*
+ * Could be a Submount, a directory entry, or a cell name we
+ * have yet to create an entry for.
+ */
+
+ /* Try a directory entry first */
+ code = cm_Lookup(dscp, NetName, CM_FLAG_NOMOUNTCHASE,
+ userp, &req, &scp);
+ if (code && code != CM_ERROR_NOACCESS)
+ code = cm_Lookup(dscp, NetName, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
+ userp, &req, &scp);
+
+ if (scp == NULL && code != CM_ERROR_NOACCESS) { /* Try a submount */
+ code = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\OpenAFS\\Client\\Submounts",
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ cblen = sizeof(pathstr);
+ code = RegQueryValueExW(parmKey, NetName, NULL, NULL,
+ (BYTE *) pathstr, &cblen);
+ if (code != ERROR_SUCCESS)
+ cblen = 0;
+ RegCloseKey (parmKey);
+ } else {
+ cblen = 0;
+ }
+
+ if (cblen) {
+ code = cm_NameI(dscp, pathstr, CM_FLAG_FOLLOW, userp, NULL, &req, &scp);
+ if (code && code != CM_ERROR_NOACCESS)
+ code = cm_NameI(dscp, pathstr, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
+ userp, NULL, &req, &scp);
+ }
+ }
+ }
+
+ if (scp) {
+ switch (Level) {
+ case 2:
+ /* for share level security */
+ InfoStruct->ShareInfo2->shi2_permissions = 0;
+ InfoStruct->ShareInfo2->shi2_max_uses = -1;
+ InfoStruct->ShareInfo2->shi2_current_uses = 0;
+ InfoStruct->ShareInfo2->shi2_path =
+ NetrIntGenerateSharePath(ServerName, &scp->fid);
+ /* must be the empty string */
+ InfoStruct->ShareInfo2->shi2_passwd = wcsdup(L"");
+ /* fall-through */
+ case 1:
+ InfoStruct->ShareInfo1->shi1_type = STYPE_DISKTREE;
+ InfoStruct->ShareInfo1->shi1_remark =
+ NetrIntGenerateShareRemark(scp, &scp->fid);
+ /* fall-through */
+ case 0:
+ /* Canonicalized version of NetName parameter */
+ InfoStruct->ShareInfo0->shi0_netname = wcsdup(NetName);
+ break;
+ case 501:
+ case 502:
+ case 503:
+ case 1004:
+ case 1005:
+ case 1006:
+ default:
+ status = ERROR_INVALID_LEVEL;
+ }
+ cm_ReleaseSCache(scp);
+ } else {
+ /*
+ * The requested object does not exist.
+ * Return the correct NERR or Win32 Error.
+ */
+ smb_MapWin32Error(code, &status);
+ switch (status) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_NAME:
+ case ERROR_BAD_NETPATH:
+ status = NERR_NetNameNotFound;
+ break;
+ }
+ }
+ return status;
+}
+
+NET_API_STATUS NetrShareSetInfo(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *NetName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][in] */ LPSHARE_INFO ShareInfo,
+ /* [unique][out][in] */ DWORD *ParmErr)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrShareDel(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *NetName,
+ /* [in] */ DWORD Reserved)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrShareDelSticky(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *NetName,
+ /* [in] */ DWORD Reserved)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrShareCheck(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *Device,
+ /* [out] */ DWORD *Type)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerGetInfo(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][out] */ LPSERVER_INFO InfoStruct)
+{
+ /*
+ * How much space do we need and do we have that much room?
+ * For now, just assume we can return everything in one shot
+ * because the reality is that in this function call we do
+ * not know the max size of the RPC response.
+ */
+ switch (Level) {
+ case 103:
+ InfoStruct->ServerInfo103 = calloc(1, sizeof(SERVER_INFO_103));
+ break;
+ case 102:
+ InfoStruct->ServerInfo102 = calloc(1, sizeof(SERVER_INFO_102));
+ break;
+ case 101:
+ InfoStruct->ServerInfo101 = calloc(1, sizeof(SERVER_INFO_101));
+ break;
+ case 100:
+ InfoStruct->ServerInfo100 = calloc(1, sizeof(SERVER_INFO_100));
+ break;
+ }
+
+ if (InfoStruct->ServerInfo100 == NULL) {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ switch (Level) {
+ case 103:
+ InfoStruct->ServerInfo103->sv103_capabilities = 0;
+ /* fall-through */
+ case 102:
+ InfoStruct->ServerInfo102->sv102_users = 0xFFFFFFFF;
+ InfoStruct->ServerInfo102->sv102_disc = SV_NODISC;
+ InfoStruct->ServerInfo102->sv102_hidden = SV_HIDDEN;
+ InfoStruct->ServerInfo102->sv102_announce = 65535;
+ InfoStruct->ServerInfo102->sv102_anndelta = 0;
+ InfoStruct->ServerInfo102->sv102_licenses = 0;
+ InfoStruct->ServerInfo102->sv102_userpath = wcsdup(L"C:\\");
+ /* fall-through */
+ case 101:
+ InfoStruct->ServerInfo101->sv101_version_major = AFSPRODUCT_VERSION_MAJOR;
+ InfoStruct->ServerInfo101->sv101_version_minor = AFSPRODUCT_VERSION_MINOR;
+ InfoStruct->ServerInfo101->sv101_type = SV_TYPE_SERVER_UNIX;
+ InfoStruct->ServerInfo101->sv101_comment = wcsdup(wAFSVersion);
+ /* fall-through */
+ case 100:
+ InfoStruct->ServerInfo100->sv100_platform_id = SV_PLATFORM_ID_AFS;
+ /* The Netbios Name */
+ InfoStruct->ServerInfo100->sv100_name = wcsdup(ServerName);
+ return 0;
+ case 502:
+ case 503:
+ case 599:
+ case 1005:
+ case 1107:
+ case 1010:
+ case 1016:
+ case 1017:
+ case 1018:
+ case 1501:
+ case 1502:
+ case 1503:
+ case 1506:
+ case 1510:
+ case 1511:
+ case 1512:
+ case 1513:
+ case 1514:
+ case 1515:
+ case 1516:
+ case 1518:
+ case 1523:
+ case 1528:
+ case 1529:
+ case 1530:
+ case 1533:
+ case 1534:
+ case 1535:
+ case 1536:
+ case 1538:
+ case 1539:
+ case 1540:
+ case 1541:
+ case 1542:
+ case 1543:
+ case 1544:
+ case 1545:
+ case 1546:
+ case 1547:
+ case 1548:
+ case 1549:
+ case 1550:
+ case 1552:
+ case 1553:
+ case 1554:
+ case 1555:
+ case 1556:
+ default:
+ return ERROR_INVALID_LEVEL;
+ }
+ return 0;
+}
+
+NET_API_STATUS NetrServerSetInfo(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][in] */ LPSERVER_INFO ServerInfo,
+ /* [unique][out][in] */ DWORD *ParmErr)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerDiskEnum(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [out][in] */ DISK_ENUM_CONTAINER *DiskInfoStruct,
+ /* [in] */ DWORD PreferedMaximumLength,
+ /* [out] */ DWORD *TotalEntries,
+ /* [unique][out][in] */ DWORD *ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerStatisticsGet(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [unique][string][in] */ WCHAR *Service,
+ /* [in] */ DWORD Level,
+ /* [in] */ DWORD Options,
+ /* [out] */ LPSTAT_SERVER_0 *InfoStruct)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerTransportAdd(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [in] */ LPSERVER_TRANSPORT_INFO_0 Buffer)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerTransportEnum(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [out][in] */ LPSERVER_XPORT_ENUM_STRUCT InfoStruct,
+ /* [in] */ DWORD PreferedMaximumLength,
+ /* [out] */ DWORD *TotalEntries,
+ /* [unique][out][in] */ DWORD *ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerTransportDel(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [in] */ LPSERVER_TRANSPORT_INFO_0 Buffer)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrRemoteTOD(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [out] */ LPTIME_OF_DAY_INFO *BufferPtr)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetprPathType(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *PathName,
+ /* [out] */ DWORD *PathType,
+ /* [in] */ DWORD Flags)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetprPathCanonicalize(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *PathName,
+ /* [size_is][out] */ unsigned char *Outbuf,
+ /* [range][in] */ DWORD OutbufLen,
+ /* [string][in] */ WCHAR *Prefix,
+ /* [out][in] */ DWORD *PathType,
+ /* [in] */ DWORD Flags)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+long NetprPathCompare(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *PathName1,
+ /* [string][in] */ WCHAR *PathName2,
+ /* [in] */ DWORD PathType,
+ /* [in] */ DWORD Flags)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetprNameValidate(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *Name,
+ /* [in] */ DWORD NameType,
+ /* [in] */ DWORD Flags)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetprNameCanonicalize(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *Name,
+ /* [size_is][out] */ WCHAR *Outbuf,
+ /* [range][in] */ DWORD OutbufLen,
+ /* [in] */ DWORD NameType,
+ /* [in] */ DWORD Flags)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+long NetprNameCompare(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *Name1,
+ /* [string][in] */ WCHAR *Name2,
+ /* [in] */ DWORD NameType,
+ /* [in] */ DWORD Flags)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrShareEnumSticky(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [out][in] */ LPSHARE_ENUM_STRUCT InfoStruct,
+ /* [in] */ DWORD PreferedMaximumLength,
+ /* [out] */ DWORD *TotalEntries,
+ /* [unique][out][in] */ DWORD *ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrShareDelStart(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *NetName,
+ /* [in] */ DWORD Reserved,
+ /* [out] */ PSHARE_DEL_HANDLE ContextHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrShareDelCommit(
+ /* [out][in] */ PSHARE_DEL_HANDLE ContextHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+DWORD NetrpGetFileSecurity(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [unique][string][in] */ WCHAR *ShareName,
+ /* [string][in] */ WCHAR *lpFileName,
+ /* [in] */ SECURITY_INFORMATION RequestedInformation,
+ /* [out] */ PADT_SECURITY_DESCRIPTOR *SecurityDescriptor)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+DWORD NetrpSetFileSecurity(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [unique][string][in] */ WCHAR *ShareName,
+ /* [string][in] */ WCHAR *lpFileName,
+ /* [in] */ SECURITY_INFORMATION SecurityInformation,
+ /* [in] */ PADT_SECURITY_DESCRIPTOR SecurityDescriptor)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerTransportAddEx(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][in] */ LPTRANSPORT_INFO Buffer)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsGetVersion(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [out] */ DWORD *Version)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsCreateLocalPartition(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *ShareName,
+ /* [in] */ GUID *EntryUid,
+ /* [string][in] */ WCHAR *EntryPrefix,
+ /* [string][in] */ WCHAR *ShortName,
+ /* [in] */ LPNET_DFS_ENTRY_ID_CONTAINER RelationInfo,
+ /* [in] */ int Force)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsDeleteLocalPartition(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ GUID *Uid,
+ /* [string][in] */ WCHAR *Prefix)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsSetLocalVolumeState(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ GUID *Uid,
+ /* [string][in] */ WCHAR *Prefix,
+ /* [in] */ unsigned long State)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsCreateExitPoint(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ GUID *Uid,
+ /* [string][in] */ WCHAR *Prefix,
+ /* [in] */ unsigned long Type,
+ /* [range][in] */ DWORD ShortPrefixLen,
+ /* [size_is][string][out] */ WCHAR *ShortPrefix)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsDeleteExitPoint(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ GUID *Uid,
+ /* [string][in] */ WCHAR *Prefix,
+ /* [in] */ unsigned long Type)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsModifyPrefix(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ GUID *Uid,
+ /* [string][in] */ WCHAR *Prefix)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsFixLocalVolume(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [string][in] */ WCHAR *VolumeName,
+ /* [in] */ unsigned long EntryType,
+ /* [in] */ unsigned long ServiceType,
+ /* [string][in] */ WCHAR *StgId,
+ /* [in] */ GUID *EntryUid,
+ /* [string][in] */ WCHAR *EntryPrefix,
+ /* [in] */ LPNET_DFS_ENTRY_ID_CONTAINER RelationInfo,
+ /* [in] */ unsigned long CreateDisposition)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrDfsManagerReportSiteInfo(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [unique][out][in] */ LPDFS_SITELIST_INFO *ppSiteInfo)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerTransportDelEx(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][in] */ LPTRANSPORT_INFO Buffer)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerAliasAdd(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][in] */ LPSERVER_ALIAS_INFO InfoStruct)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerAliasEnum(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [out][in] */ LPSERVER_ALIAS_ENUM_STRUCT InfoStruct,
+ /* [in] */ DWORD PreferedMaximumLength,
+ /* [out] */ LPDWORD TotalEntries,
+ /* [unique][out][in] */ LPDWORD ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrServerAliasDel(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][in] */ LPSERVER_ALIAS_INFO InfoStruct)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+NET_API_STATUS NetrShareDelEx(
+ /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
+ /* [in] */ DWORD Level,
+ /* [switch_is][in] */ LPSHARE_INFO ShareInfo)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+
+void __RPC_USER SHARE_DEL_HANDLE_rundown( SHARE_DEL_HANDLE h)
+{
+}
+
+/* [nocode] */ void Opnum0NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum1NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum2NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+#if 0
+/* [nocode] */ void Opnum3NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum4NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+#endif
+
+/* [nocode] */ void Opnum5NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum6NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum7NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum29NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum42NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum47NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2009 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <windows.h>
+#include <lmcons.h>
+#include <stdlib.h>
+#include "ms-wkssvc.h"
+#include "AFS_component_version_number.h"
+
+#define PLATFORM_ID_AFS 800
+
+#pragma warning( disable: 4027 ) /* func w/o formal parameter list */
+
+unsigned long NetrWkstaGetInfo(
+ /* [unique][string][in] */ WKSSVC_IDENTIFY_HANDLE ServerName,
+ /* [in] */ unsigned long Level,
+ /* [switch_is][out] */ LPWKSTA_INFO WkstaInfo)
+{
+ /*
+ * How much space do we need and do we have that much room?
+ * For now, just assume we can return everything in one shot
+ * because the reality is that in this function call we do
+ * not know the max size of the RPC response.
+ */
+ switch (Level) {
+ case 100:
+ WkstaInfo->WkstaInfo100 = calloc(1, sizeof(WKSTA_INFO_100));
+ break;
+ }
+
+ if (WkstaInfo->WkstaInfo100 == NULL) {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ switch (Level) {
+ case 100:
+ WkstaInfo->WkstaInfo100->wki100_platform_id = PLATFORM_ID_AFS;
+ WkstaInfo->WkstaInfo100->wki100_computername = wcsdup(ServerName);
+ WkstaInfo->WkstaInfo100->wki100_ver_major = AFSPRODUCT_VERSION_MAJOR;
+ WkstaInfo->WkstaInfo100->wki100_ver_major = AFSPRODUCT_VERSION_MINOR;
+ return 0;
+ case 502:
+ case 1013:
+ case 1018:
+ case 1046:
+ default:
+ return ERROR_INVALID_LEVEL;
+ }
+}
+
+unsigned long NetrWkstaSetInfo(
+ /* [unique][string][in] */ WKSSVC_IDENTIFY_HANDLE ServerName,
+ /* [in] */ unsigned long Level,
+ /* [switch_is][in] */ LPWKSTA_INFO WkstaInfo,
+ /* [unique][out][in] */ unsigned long *ErrorParameter)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrWkstaUserEnum(
+ /* [unique][string][in] */ WKSSVC_IDENTIFY_HANDLE ServerName,
+ /* [out][in] */ LPWKSTA_USER_ENUM_STRUCT UserInfo,
+ /* [in] */ unsigned long PreferredMaximumLength,
+ /* [out] */ unsigned long *TotalEntries,
+ /* [unique][out][in] */ unsigned long *ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrWkstaTransportEnum(
+ /* [unique][string][in] */ WKSSVC_IDENTIFY_HANDLE ServerName,
+ /* [out][in] */ LPWKSTA_TRANSPORT_ENUM_STRUCT TransportInfo,
+ /* [in] */ unsigned long PreferredMaximumLength,
+ /* [out] */ unsigned long *TotalEntries,
+ /* [unique][out][in] */ unsigned long *ResumeHandle)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrWkstaTransportAdd(
+ /* [unique][string][in] */ WKSSVC_IDENTIFY_HANDLE ServerName,
+ /* [in] */ unsigned long Level,
+ /* [in] */ LPWKSTA_TRANSPORT_INFO_0 TransportInfo,
+ /* [unique][out][in] */ unsigned long *ErrorParameter)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrWkstaTransportDel(
+ /* [unique][string][in] */ WKSSVC_IDENTIFY_HANDLE ServerName,
+ /* [unique][string][in] */ wchar_t *TransportName,
+ /* [in] */ unsigned long ForceLevel)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrWorkstationStatisticsGet(
+ /* [unique][string][in] */ WKSSVC_IDENTIFY_HANDLE ServerName,
+ /* [unique][string][in] */ wchar_t *ServiceName,
+ /* [in] */ unsigned long Level,
+ /* [in] */ unsigned long Options,
+ /* [out] */ LPSTAT_WORKSTATION_0 *Buffer)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrGetJoinInformation(
+ /* [unique][string][in] */ WKSSVC_IMPERSONATE_HANDLE ServerName,
+ /* [string][out][in] */ wchar_t **NameBuffer,
+ /* [out] */ PNETSETUP_JOIN_STATUS BufferType)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrJoinDomain2(
+ /* [in] */ handle_t RpcBindingHandle,
+ /* [unique][string][in] */ wchar_t *ServerName,
+ /* [string][in] */ wchar_t *DomainName,
+ /* [unique][string][in] */ wchar_t *MachineAccountOU,
+ /* [unique][string][in] */ wchar_t *AccountName,
+ /* [unique][in] */ PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ /* [in] */ unsigned long Options)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrUnjoinDomain2(
+ /* [in] */ handle_t RpcBindingHandle,
+ /* [unique][string][in] */ wchar_t *ServerName,
+ /* [unique][string][in] */ wchar_t *AccountName,
+ /* [unique][in] */ PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ /* [in] */ unsigned long Options)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrRenameMachineInDomain2(
+ /* [in] */ handle_t RpcBindingHandle,
+ /* [unique][string][in] */ wchar_t *ServerName,
+ /* [unique][string][in] */ wchar_t *MachineName,
+ /* [unique][string][in] */ wchar_t *AccountName,
+ /* [unique][in] */ PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ /* [in] */ unsigned long Options)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrValidateName2(
+ /* [in] */ handle_t RpcBindingHandle,
+ /* [unique][string][in] */ wchar_t *ServerName,
+ /* [string][in] */ wchar_t *NameToValidate,
+ /* [unique][string][in] */ wchar_t *AccountName,
+ /* [unique][in] */ PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ /* [in] */ NETSETUP_NAME_TYPE NameType)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrGetJoinableOUs2(
+ /* [in] */ handle_t RpcBindingHandle,
+ /* [unique][string][in] */ wchar_t *ServerName,
+ /* [string][in] */ wchar_t *DomainName,
+ /* [unique][string][in] */ wchar_t *AccountName,
+ /* [unique][in] */ PJOINPR_ENCRYPTED_USER_PASSWORD Password,
+ /* [out][in] */ unsigned long *OUCount,
+ /* [size_is][size_is][string][out] */ wchar_t ***OUs)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrAddAlternateComputerName(
+ /* [in] */ handle_t RpcBindingHandle,
+ /* [unique][string][in] */ wchar_t *ServerName,
+ /* [unique][string][in] */ wchar_t *AlternateName,
+ /* [unique][string][in] */ wchar_t *DomainAccount,
+ /* [unique][in] */ PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
+ /* [in] */ unsigned long Reserved)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrRemoveAlternateComputerName(
+ /* [in] */ handle_t RpcBindingHandle,
+ /* [unique][string][in] */ wchar_t *ServerName,
+ /* [unique][string][in] */ wchar_t *AlternateName,
+ /* [unique][string][in] */ wchar_t *DomainAccount,
+ /* [unique][in] */ PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
+ /* [in] */ unsigned long Reserved)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrSetPrimaryComputerName(
+ /* [in] */ handle_t RpcBindingHandle,
+ /* [unique][string][in] */ wchar_t *ServerName,
+ /* [unique][string][in] */ wchar_t *PrimaryName,
+ /* [unique][string][in] */ wchar_t *DomainAccount,
+ /* [unique][in] */ PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
+ /* [in] */ unsigned long Reserved)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+unsigned long NetrEnumerateComputerNames(
+ /* [unique][string][in] */ WKSSVC_IMPERSONATE_HANDLE ServerName,
+ /* [in] */ NET_COMPUTER_NAME_TYPE NameType,
+ /* [in] */ unsigned long Reserved,
+ /* [out] */ PNET_COMPUTER_NAME_ARRAY *ComputerNames)
+{
+ return ERROR_NOT_SUPPORTED;
+}
+
+/* [nocode] */ void Opnum3NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum4NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum8NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum9NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum10NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum11NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum12NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+
+/* [nocode] */ void Opnum14NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum15NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum16NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum17NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum18NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+/* [nocode] */ void Opnum19NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
+
+/* [nocode] */ void Opnum21NotUsedOnWire(
+ /* [in] */ handle_t IDL_handle)
+{
+}
+
case 63:
return "RAP(63)NetWkStaGetInfo";
}
-}
+}
+
+char * myCrt_NmpipeDispatch(int i)
+{
+ switch(i) {
+ case SMB_TRANS_SET_NMPIPE_STATE:
+ return "SET NMPIPE STATE";
+
+ case SMB_TRANS_RAW_READ_NMPIPE:
+ return "RAW READ NMPIPE";
+
+ case SMB_TRANS_QUERY_NMPIPE_STATE:
+ return "QUERY NMPIPE STATE";
+
+ case SMB_TRANS_QUERY_NMPIPE_INFO:
+ return "QUERY NMPIPE INFO";
+
+ case SMB_TRANS_PEEK_NMPIPE:
+ return "PEEK NMPIPE";
+
+ case SMB_TRANS_TRANSACT_NMPIPE:
+ return "TRANSACT NMPIPE";
+
+ case SMB_TRANS_RAW_WRITE_NMPIPE:
+ return "WRITE NMPIPE";
+
+ case SMB_TRANS_READ_NMPIPE:
+ return "READ NMPIPE";
+
+ case SMB_TRANS_WRITE_NMPIPE:
+ return "WRITE NMPIPE";
+
+ case SMB_TRANS_WAIT_NMPIPE:
+ return "WAIT NMPIPE";
+
+ case SMB_TRANS_CALL_NMPIPE:
+ return "CALL NMPIPE";
+ }
+ return "(Unknown)";
+}
/* scache must be locked */
unsigned int smb_Attributes(cm_scache_t *scp)
if (ioctlp->ioctl.outAllocp)
free(ioctlp->ioctl.outAllocp);
free(ioctlp);
- }
+ }
+
+ smb_CleanupRPCFid(fidp);
+
lock_ReleaseMutex(&fidp->mx);
lock_FinalizeMutex(&fidp->mx);
free(fidp);
}
else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
NTStatus = 0xC0000055L; /* Lock Not Granted */
- } else if (code == ENOMEM) {
+ }
+ else if (code == ENOMEM) {
NTStatus = 0xC0000017L; /* Out of Memory */
- } else {
+ }
+ else if (code == CM_ERROR_RPC_MOREDATA) {
+ NTStatus = 0x80000005L; /* Buffer overflow */
+ }
+ else {
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus);
}
+/*
+ * NTSTATUS <-> Win32 Error Translation
+ * http://support.microsoft.com/kb/113996
+ */
+void smb_MapWin32Error(long code, unsigned long *Win32Ep)
+{
+ unsigned long Win32E;
+
+ /* map CM_ERROR_* errors to Win32 32-bit error codes */
+ if (code == 0) {
+ Win32E = 0;
+ }
+ else if (code == CM_ERROR_NOSUCHCELL) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+ }
+ else if (code == CM_ERROR_NOSUCHVOLUME) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+ }
+ else if (code == CM_ERROR_TIMEDOUT) {
+#ifdef COMMENT
+ Win32E = ERROR_SHARING_PAUSED; /* Sharing Paused */
+#else
+ Win32E = ERROR_UNEXP_NET_ERR; /* Timeout */
+#endif
+ }
+ else if (code == CM_ERROR_RETRY) {
+ Win32E = ERROR_RETRY; /* Retry */
+ }
+ else if (code == CM_ERROR_NOACCESS) {
+ Win32E = ERROR_ACCESS_DENIED; /* Access denied */
+ }
+ else if (code == CM_ERROR_READONLY) {
+ Win32E = ERROR_WRITE_PROTECT; /* Write protected */
+ }
+ else if (code == CM_ERROR_NOSUCHFILE ||
+ code == CM_ERROR_BPLUS_NOMATCH) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+ }
+ else if (code == CM_ERROR_NOSUCHPATH) {
+ Win32E = ERROR_PATH_NOT_FOUND; /* Object path not found */
+ }
+ else if (code == CM_ERROR_TOOBIG) {
+ Win32E = ERROR_BAD_EXE_FORMAT; /* Invalid image format */
+ }
+ else if (code == CM_ERROR_INVAL) {
+ Win32E = ERROR_INVALID_PARAMETER;/* Invalid parameter */
+ }
+ else if (code == CM_ERROR_BADFD) {
+ Win32E = ERROR_INVALID_HANDLE; /* Invalid handle */
+ }
+ else if (code == CM_ERROR_BADFDOP) {
+ Win32E = ERROR_ACCESS_DENIED; /* Access denied */
+ }
+ else if (code == CM_ERROR_EXISTS) {
+ Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
+ }
+ else if (code == CM_ERROR_NOTEMPTY) {
+ Win32E = ERROR_DIR_NOT_EMPTY; /* Directory not empty */
+ }
+ else if (code == CM_ERROR_CROSSDEVLINK) {
+ Win32E = ERROR_NOT_SAME_DEVICE; /* Not same device */
+ }
+ else if (code == CM_ERROR_NOTDIR) {
+ Win32E = ERROR_DIRECTORY; /* Not a directory */
+ }
+ else if (code == CM_ERROR_ISDIR) {
+ Win32E = ERROR_ACCESS_DENIED; /* File is a directory */
+ }
+ else if (code == CM_ERROR_BADOP) {
+ Win32E = ERROR_NOT_SUPPORTED; /* Not supported */
+ }
+ else if (code == CM_ERROR_BADSHARENAME) {
+ Win32E = ERROR_BAD_NETPATH; /* Bad network path (server valid, share bad) */
+ }
+ else if (code == CM_ERROR_NOIPC) {
+#ifdef COMMENT
+ Win32E = ERROR_ACCESS_DENIED; /* Access Denied */
+#else
+ Win32E = ERROR_REM_NOT_LIST; /* Remote Resources */
+#endif
+ }
+ else if (code == CM_ERROR_CLOCKSKEW) {
+ Win32E = ERROR_TIME_SKEW; /* Time difference at DC */
+ }
+ else if (code == CM_ERROR_BADTID) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* SMB bad TID */
+ }
+ else if (code == CM_ERROR_USESTD) {
+ Win32E = ERROR_ACCESS_DENIED; /* SMB use standard */
+ }
+ else if (code == CM_ERROR_QUOTA) {
+ Win32E = ERROR_NOT_ENOUGH_QUOTA;/* Quota exceeded */
+ }
+ else if (code == CM_ERROR_SPACE) {
+ Win32E = ERROR_DISK_FULL; /* Disk full */
+ }
+ else if (code == CM_ERROR_ATSYS) {
+ Win32E = ERROR_INVALID_NAME; /* Object name invalid */
+ }
+ else if (code == CM_ERROR_BADNTFILENAME) {
+ Win32E = ERROR_INVALID_NAME; /* Object name invalid */
+ }
+ else if (code == CM_ERROR_WOULDBLOCK) {
+ Win32E = WAIT_TIMEOUT; /* Can't wait */
+ }
+ else if (code == CM_ERROR_SHARING_VIOLATION) {
+ Win32E = ERROR_SHARING_VIOLATION; /* Sharing violation */
+ }
+ else if (code == CM_ERROR_LOCK_CONFLICT) {
+ Win32E = ERROR_LOCK_VIOLATION; /* Lock conflict */
+ }
+ else if (code == CM_ERROR_PARTIALWRITE) {
+ Win32E = ERROR_DISK_FULL; /* Disk full */
+ }
+ else if (code == CM_ERROR_BUFFERTOOSMALL) {
+ Win32E = ERROR_INSUFFICIENT_BUFFER; /* Buffer too small */
+ }
+ else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+ Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
+ }
+ else if (code == CM_ERROR_BADPASSWORD) {
+ Win32E = ERROR_LOGON_FAILURE; /* unknown username or bad password */
+ }
+ else if (code == CM_ERROR_BADLOGONTYPE) {
+ Win32E = ERROR_INVALID_LOGON_TYPE; /* logon type not granted */
+ }
+ else if (code == CM_ERROR_GSSCONTINUE) {
+ Win32E = ERROR_MORE_DATA; /* more processing required */
+ }
+ else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
+#ifdef COMMENT
+ Win32E = ERROR_CANT_RESOLVE_FILENAME; /* reparse point not resolved */
+#else
+ Win32E = ERROR_ACCESS_DENIED; /* Access Denied */
+#endif
+ }
+ else if (code == CM_ERROR_PATH_NOT_COVERED) {
+ Win32E = ERROR_HOST_UNREACHABLE; /* Path Not Covered */
+ }
+ else if (code == CM_ERROR_ALLBUSY) {
+ Win32E = ERROR_RETRY; /* Retry */
+ }
+ else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
+ Win32E = ERROR_HOST_UNREACHABLE; /* Path not found */
+ }
+ else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
+ Win32E = SEC_E_NO_KERB_KEY; /* No Kerberos key */
+ }
+ else if (code == CM_ERROR_BAD_LEVEL) {
+ Win32E = ERROR_INVALID_LEVEL; /* Invalid Level */
+ }
+ else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
+ Win32E = ERROR_NOT_LOCKED; /* Range Not Locked */
+ }
+ else if (code == CM_ERROR_NOSUCHDEVICE) {
+ Win32E = ERROR_FILE_NOT_FOUND; /* No Such Device */
+ }
+ else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
+ Win32E = ERROR_LOCK_VIOLATION; /* Lock Not Granted */
+ }
+ else if (code == ENOMEM) {
+ Win32E = ERROR_NOT_ENOUGH_MEMORY; /* Out of Memory */
+ }
+ else if (code == CM_ERROR_RPC_MOREDATA) {
+ Win32E = ERROR_MORE_DATA; /* Buffer overflow */
+ }
+ else {
+ Win32E = ERROR_GEN_FAILURE; /* SMB non-specific error */
+ }
+
+ *Win32Ep = Win32E;
+ osi_Log2(smb_logp, "SMB SEND code %lX as Win32 %lX", code, Win32E);
+}
+
void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
unsigned char *classp)
{
if (!userp) {
lock_ObtainMutex(&fidp->mx);
- if (!fidp->userp && !(fidp->flags & SMB_FID_IOCTL)) {
+ if (!fidp->userp && !(fidp->flags & (SMB_FID_IOCTL|
+ SMB_FID_RPC))) {
lock_ReleaseMutex(&fidp->mx);
osi_Log0(smb_logp, " No user specified. Not closing fid");
return CM_ERROR_BADFD;
return code;
}
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_RPCWrite(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ osi_Log1(smb_logp, "smb_ReceiveCoreWrite RPC code 0x%x", code);
+ return code;
+ }
+
if (!fidp->scp) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
return code;
}
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_RPCRead(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
if (!fidp->scp) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
#define SMB_FIND_FILE_NAMES_INFO 0x103
#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
+/* SMB_COM_TRANSACTION Named pipe operations */
+#define SMB_TRANS_SET_NMPIPE_STATE 0x0001
+#define SMB_TRANS_RAW_READ_NMPIPE 0x0011
+#define SMB_TRANS_QUERY_NMPIPE_STATE 0x0021
+#define SMB_TRANS_QUERY_NMPIPE_INFO 0x0022
+#define SMB_TRANS_PEEK_NMPIPE 0x0023
+#define SMB_TRANS_TRANSACT_NMPIPE 0x0026
+#define SMB_TRANS_RAW_WRITE_NMPIPE 0x0031
+#define SMB_TRANS_READ_NMPIPE 0x0036
+#define SMB_TRANS_WRITE_NMPIPE 0x0037
+#define SMB_TRANS_WAIT_NMPIPE 0x0053
+#define SMB_TRANS_CALL_NMPIPE 0x0054
+
/* more defines */
#define SMB_NOPCODES 256 /* # of opcodes in the dispatch table */
/* Defined in smb_ioctl.h */
struct smb_ioctl;
+/* Defined in smb_rpc.h */
+struct smb_rpc;
+
/* one per file ID; these are really file descriptors */
typedef struct smb_fid {
osi_queue_t q;
the file if session is
terminated) */
osi_hyper_t offset; /* our file pointer */
- struct smb_ioctl *ioctlp; /* ptr to ioctl structure */
+ struct smb_ioctl *ioctlp; /* ptr to ioctl structure */
/* Under NT, we may need to know the
* parent directory and pathname used
* to open the file, either to delete
* the file on close, or to do a
* change notification */
+ struct smb_rpc *rpcp; /* ptr to RPC structure. Used
+ to keep track of endpoint
+ that was opened for the
+ RPC. */
struct cm_scache *NTopen_dscp; /* parent directory (NT) */
clientchar_t *NTopen_pathp; /* path used in open (NT) */
clientchar_t *NTopen_wholepathp; /* entire path, not just last name */
#define SMB_FID_SHARE_READ 0x1000
#define SMB_FID_SHARE_WRITE 0x2000
+#define SMB_FID_RPC 0x4000 /* open for MS RPC */
+#define SMB_FID_MESSAGEMODEPIPE 0x8000 /* message mode pipe */
+#define SMB_FID_BLOCKINGPIPE 0x10000 /* blocking pipe */
+#define SMB_FID_RPC_INCALL 0x20000 /* in an RPC call */
+
#define SMB_FID_QLOCK_HIGH 0x7f000000
#define SMB_FID_QLOCK_LOW 0x00000000
#define SMB_FID_QLOCK_LENGTH 1
#define LOCKING_ANDX_CANCEL_LOCK 0x08 /* Cancel outstanding request */
#define LOCKING_ANDX_LARGE_FILES 0x10 /* Large file locking format */
+/* File type constants */
+#define SMB_FILETYPE_DISK 0x0000
+#define SMB_FILETYPE_BYTE_MODE_PIPE 0x0001
+#define SMB_FILETYPE_MESSAGE_MODE_PIPE 0x0002
+#define SMB_FILETYPE_PRINTER 0x0003
+#define SMB_FILETYPE_UNKNOWN 0xffff
+
+/* Device state constants */
+#define SMB_DEVICESTATE_READASBYTESTREAM 0x0000
+#define SMB_DEVICESTATE_READMSGFROMPIPE 0x0100
+#define SMB_DEVICESTATE_BYTESTREAMPIPE 0x0000
+#define SMB_DEVICESTATE_MESSAGEMODEPIPE 0x0400
+#define SMB_DEVICESTATE_PIPECLIENTEND 0x0000
+#define SMB_DEVICESTATE_PIPESERVEREND 0x4000
+#define SMB_DEVICESTATE_BLOCKING 0x8000
+
/* for tracking in-progress directory searches */
typedef struct smb_dirSearch {
osi_queue_t q; /* queue of all outstanding cookies */
extern void smb_MapNTError(long code, unsigned long *NTStatusp);
+extern void smb_MapWin32Error(long code, unsigned long *Win32Ep);
+
/* some globals, too */
extern char *smb_localNamep;
extern char *myCrt_RapDispatch(int i);
+extern char * myCrt_NmpipeDispatch(int i);
+
extern unsigned int smb_Attributes(cm_scache_t *scp);
extern int smb_ChainFID(int fid, smb_packet_t *inp);
#include "smb3.h"
#include "smb_ioctl.h"
#include "smb_iocons.h"
+#include "smb_rpc.h"
cm_user_t *smb_FindOrCreateUser(smb_vc_t *vcp, clientchar_t *usern);
free(t2p->parmsp);
if (t2p->datap)
free(t2p->datap);
- }
+ }
+ if (t2p->name) {
+ free(t2p->name);
+ t2p->name = NULL;
+ }
while (t2p->stringsp) {
cm_space_t * ns;
smbp->uid = t2p->uid;
smbp->res[0] = t2p->res[0];
+ if (t2p->error_code) {
+ if (vcp->flags & SMB_VCFLAG_STATUS32) {
+ unsigned long NTStatus;
+
+ smb_MapNTError(t2p->error_code, &NTStatus);
+
+ smbp->rcls = (unsigned char) (NTStatus & 0xff);
+ smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
+ smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
+ smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
+ smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
+ }
+ else {
+ unsigned short errCode;
+ unsigned char errClass;
+
+ smb_MapCoreError(t2p->error_code, vcp, &errCode, &errClass);
+
+ smbp->rcls = errClass;
+ smbp->errLow = (unsigned char) (errCode & 0xff);
+ smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
+ }
+ }
+
totalLength = 1 + t2p->totalData + t2p->totalParms;
/* now add the core parameters (tran2 info) to the packet */
/* next, send the datagram */
smb_SendPacket(vcp, tp);
-}
+}
+
+/* TRANS_SET_NMPIPE_STATE */
+long smb_nmpipeSetState(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+ smb_fid_t *fidp;
+ int fd;
+ int pipeState = 0x0100; /* default */
+ smb_tran2Packet_t *outp = NULL;
+
+ fd = p->pipeParam;
+ if (p->totalParms > 0)
+ pipeState = p->parmsp[0];
+
+ osi_Log2(smb_logp, "smb_nmpipeSetState for fd[%d] with state[0x%x]", fd, pipeState);
+
+ fidp = smb_FindFID(vcp, fd, 0);
+ if (!fidp)
+ return CM_ERROR_BADFD;
+
+ lock_ObtainMutex(&fidp->mx);
+ if (pipeState & 0x8000)
+ fidp->flags |= SMB_FID_BLOCKINGPIPE;
+ if (pipeState & 0x0100)
+ fidp->flags |= SMB_FID_MESSAGEMODEPIPE;
+ lock_ReleaseMutex(&fidp->mx);
+
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 0);
+ smb_SendTran2Packet(vcp, outp, op);
+ smb_FreeTran2Packet(outp);
+
+ smb_ReleaseFID(fidp);
+
+ return 0;
+}
+
+long smb_nmpipeTransact(smb_vc_t * vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+ smb_fid_t *fidp;
+ int fd;
+ int is_rpc = 0;
+
+ long code = 0;
+
+ fd = p->pipeParam;
+
+ osi_Log3(smb_logp, "smb_nmpipeTransact for fd[%d] %d bytes in, %d max bytes out",
+ fd, p->totalData, p->maxReturnData);
+
+ fidp = smb_FindFID(vcp, fd, 0);
+ if (!fidp)
+ return CM_ERROR_BADFD;
+
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->flags & SMB_FID_RPC) {
+ is_rpc = 1;
+ }
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (is_rpc) {
+ code = smb_RPCNmpipeTransact(fidp, vcp, p, op);
+ smb_ReleaseFID(fidp);
+ } else {
+ /* We only deal with RPC pipes */
+ code = CM_ERROR_BADFD;
+ }
+
+ return code;
+}
/* SMB_COM_TRANSACTION and SMB_COM_TRANSACTION_SECONDARY */
dataOffset = smb_GetSMBParm(inp, 12);
parmCount = smb_GetSMBParm(inp, 9);
dataCount = smb_GetSMBParm(inp, 11);
+ asp->setupCount = smb_GetSMBParmByte(inp, 13);
asp->maxReturnParms = smb_GetSMBParm(inp, 2);
asp->maxReturnData = smb_GetSMBParm(inp, 3);
osi_Log3(smb_logp, "SMB3 received Trans init packet total data %d, cur data %d, max return data %d",
totalData, dataCount, asp->maxReturnData);
+
+ if (asp->setupCount == 2) {
+ clientchar_t * pname;
+
+ asp->pipeCommand = smb_GetSMBParm(inp, 14);
+ asp->pipeParam = smb_GetSMBParm(inp, 15);
+ pname = smb_ParseString(inp, inp->wctp + 35, NULL, 0);
+ if (pname) {
+ asp->name = cm_ClientStrDup(pname);
+ }
+
+ osi_Log2(smb_logp, " Named Pipe command id [%d] with name [%S]",
+ asp->pipeCommand, osi_LogSaveClientString(smb_logp, asp->name));
+ }
}
else {
parmDisp = smb_GetSMBParm(inp, 4);
osi_Log2(smb_logp, "SMB3 received Trans aux packet parms %d, data %d",
parmCount, dataCount);
- }
+ }
/* now copy the parms and data */
if ( asp->totalParms > 0 && parmCount != 0 )
asp->curParms += parmCount;
/* finally, if we're done, remove the packet from the queue and dispatch it */
- if (asp->totalParms > 0 &&
- asp->curParms > 0 &&
+ if (((asp->totalParms > 0 && asp->curParms > 0)
+ || asp->setupCount == 2) &&
asp->totalData <= asp->curData &&
asp->totalParms <= asp->curParms) {
+
/* we've received it all */
lock_ObtainWrite(&smb_globalLock);
osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
lock_ReleaseWrite(&smb_globalLock);
- /* now dispatch it */
- rapOp = asp->parmsp[0];
+ switch(asp->setupCount) {
+ case 0:
+ { /* RAP */
+ rapOp = asp->parmsp[0];
- if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES && smb_rapDispatchTable[rapOp].procp) {
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
- code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return code 0x%x vcp[%x] lana[%d] lsn[%d]",code,vcp,vcp->lana,vcp->lsn);
- }
- else {
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
- code = CM_ERROR_BADOP;
- }
+ if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES &&
+ smb_rapDispatchTable[rapOp].procp) {
+
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",
+ myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
+
+ code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
+
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return code 0x%x vcp[%x] lana[%d] lsn[%d]",
+ code,vcp,vcp->lana,vcp->lsn);
+ }
+ else {
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]",
+ rapOp, vcp, vcp->lana, vcp->lsn);
+
+ code = CM_ERROR_BADOP;
+ }
+ }
+ break;
+
+ case 2:
+ { /* Named pipe operation */
+ osi_Log2(smb_logp, "Named Pipe: %s with name [%S]",
+ myCrt_NmpipeDispatch(asp->pipeCommand),
+ osi_LogSaveClientString(smb_logp, asp->name));
+
+ code = CM_ERROR_BADOP;
+
+ switch (asp->pipeCommand) {
+ case SMB_TRANS_SET_NMPIPE_STATE:
+ code = smb_nmpipeSetState(vcp, asp, outp);
+ break;
+
+ case SMB_TRANS_RAW_READ_NMPIPE:
+ break;
+
+ case SMB_TRANS_QUERY_NMPIPE_STATE:
+ break;
+
+ case SMB_TRANS_QUERY_NMPIPE_INFO:
+ break;
+
+ case SMB_TRANS_PEEK_NMPIPE:
+ break;
+
+ case SMB_TRANS_TRANSACT_NMPIPE:
+ code = smb_nmpipeTransact(vcp, asp, outp);
+ break;
+
+ case SMB_TRANS_RAW_WRITE_NMPIPE:
+ break;
+
+ case SMB_TRANS_READ_NMPIPE:
+ break;
+
+ case SMB_TRANS_WRITE_NMPIPE:
+ break;
+
+ case SMB_TRANS_WAIT_NMPIPE:
+ break;
+
+ case SMB_TRANS_CALL_NMPIPE:
+ break;
+ }
+ }
+ break;
+
+ default:
+ code = CM_ERROR_BADOP;
+ }
/* if an error is returned, we're supposed to send an error packet,
* otherwise the dispatched function already did the data sending.
clientchar_t *tidPathp;
cm_req_t req;
int created = 0;
+ BOOL is_rpc = FALSE;
smb_InitReq(&req);
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+ /* The 'is_rpc' assignment to TRUE is intentional */
if (lastNamep &&
(cm_ClientStrCmpI(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\ipc$")) == 0)) {
+ ((cm_ClientStrCmpI(lastNamep, _C("\\srvsvc")) == 0 ||
+ cm_ClientStrCmpI(lastNamep, _C("\\wkssvc")) == 0 ||
+ cm_ClientStrCmpI(lastNamep, _C("\\ipc$")) == 0) && (is_rpc = TRUE)))) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
+
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
+
+ if (is_rpc) {
+ code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log2(smb_logp, "smb_ReceiveTran2Open Creating RPC Fid [%d] code [%d]",
+ fidp->fid, code);
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "smb_ReceiveTran2Open Creating IOCTL Fid [%d]", fidp->fid);
+ }
/* copy out remainder of the parms */
parmSlot = 0;
outp->parmsp[parmSlot++] = 0; /* len */
outp->parmsp[parmSlot++] = 0x7fff;
outp->parmsp[parmSlot++] = openMode;
- outp->parmsp[parmSlot++] = 0; /* file type 0 ==> normal file or dir */
- outp->parmsp[parmSlot++] = 0; /* IPC junk */
+ outp->parmsp[parmSlot++] = file_type;
+ outp->parmsp[parmSlot++] = device_state;
}
/* and the final "always present" stuff */
outp->parmsp[parmSlot++] = 1; /* openAction found existing file */
clientchar_t *tidPathp;
cm_req_t req;
int created = 0;
+ BOOL is_rpc = FALSE;
smb_InitReq(&req);
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+ /* The 'is_rpc' assignment to TRUE is intentional */
if (lastNamep &&
(cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0)) {
+ ((cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
+ cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
+ cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0) && (is_rpc = TRUE)))) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
+
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
#endif
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
+ if (is_rpc) {
+ smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log1(smb_logp, "OpenAndX Setting up RPC on fid[%d]", fidp->fid);
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "OpenAndX Setting up IOCTL on fid[%d]", fidp->fid);
+ }
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* len */
smb_SetSMBParm(outp, parmSlot, 0x7fff); parmSlot++;
smb_SetSMBParm(outp, parmSlot, openMode); parmSlot++;
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* file type 0 ==> normal file or dir */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* IPC junk */
- }
+ smb_SetSMBParm(outp, parmSlot, file_type); parmSlot++;
+ smb_SetSMBParm(outp, parmSlot, device_state); parmSlot++;
+ }
/* and the final "always present" stuff */
smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
/* next write out the "unique" ID */
return code;
}
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_RPCV3Write(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
if (!fidp->scp) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
cm_key_t key;
char *op;
- fd = smb_GetSMBParm(inp, 2);
- count = smb_GetSMBParm(inp, 5);
+ fd = smb_GetSMBParm(inp, 2); /* File ID */
+ count = smb_GetSMBParm(inp, 5); /* MaxCount */
offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
if (*inp->wctp == 12) {
}
lock_ObtainMutex(&fidp->mx);
+
+ if (fidp->flags & SMB_FID_IOCTL) {
+ lock_ReleaseMutex(&fidp->mx);
+ inp->fid = fd;
+ code = smb_IoctlV3Read(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ inp->fid = fd;
+ code = smb_RPCV3Read(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
scp = fidp->scp;
cm_HoldSCache(scp);
+
lock_ReleaseMutex(&fidp->mx);
pid = smbp->pid;
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fd;
- lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_IOCTL) {
- lock_ReleaseMutex(&fidp->mx);
- code = smb_IoctlV3Read(fidp, vcp, inp, outp);
- smb_ReleaseFID(fidp);
- return code;
- }
- lock_ReleaseMutex(&fidp->mx);
-
userp = smb_GetUserFromVCP(vcp, inp);
/* 0 and 1 are reserved for request chaining, were setup by our caller,
int prefetch = 0;
int checkDoneRequired = 0;
cm_lock_data_t *ldp = NULL;
+ BOOL is_rpc = FALSE;
smb_InitReq(&req);
osi_Log4(smb_logp,"... da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
osi_Log3(smb_logp,"... share=[%x] flags=[%x] lastNamep=[%S]", shareAccess, flags, osi_LogSaveClientString(smb_logp,(lastNamep?lastNamep:_C("null"))));
- if (lastNamep &&
- (cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0)) {
- /* special case magic file name for receiving IOCTL requests
- * (since IOCTL calls themselves aren't getting through).
- */
+ /* The 'is_rpc' assignment to TRUE is intentional */
+ if (lastNamep &&
+ (((cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
+ cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
+ cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0) && (is_rpc = TRUE)) ||
+
+ /* special case magic file name for receiving IOCTL requests
+ * (since IOCTL calls themselves aren't getting through).
+ */
+ cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0)) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
+
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
- osi_Log1(smb_logp,"NTCreateX Setting up IOCTL on fid[%d]",fidp->fid);
+
+ if (is_rpc) {
+ smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log1(smb_logp, "NTCreateX Setting up RPC on fid[%d]", fidp->fid);
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "NTCreateX Setting up IOCTL on fid[%d]", fidp->fid);
+ }
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
sz.HighPart = 0x7fff; sz.LowPart = 0;
smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* alen */
smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* len */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */
+ smb_SetSMBParm(outp, parmSlot, file_type); parmSlot++; /* filetype */
+ smb_SetSMBParm(outp, parmSlot, device_state); parmSlot++; /* dev state */
smb_SetSMBParmByte(outp, parmSlot, 0); /* is a dir? */
smb_SetSMBDataLength(outp, 0);
int curParms; /* current # of received parm bytes */
int maxReturnData; /* max # of returned data bytes */
int maxReturnParms; /* max # of returned parm bytes */
+ int setupCount; /* setup count field */
int opcode; /* subopcode we're handling */
long flags; /* flags */
smb_vc_t *vcp; /* virtual circuit we're dealing with */
unsigned short pid; /* pid to remember */
unsigned short uid; /* uid to remember */
unsigned short res[6]; /* contains PidHigh */
+ unsigned int error_code; /* CM error code for the packet */
unsigned short *parmsp; /* parms */
unsigned char *datap; /* data bytes */
+ int pipeCommand; /* named pipe command code */
+ int pipeParam; /* pipe parameter, if there is one */
+ clientchar_t *name; /* contents of Name
+ field. Only used for Named
+ pipes */
cm_space_t * stringsp; /* decoded strings */
} smb_tran2Packet_t;
extern smb_tran2Dispatch_t smb_rapDispatchTable[SMB_RAP_NOPCODES];
+extern smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
+ smb_tran2Packet_t *inp, smb_packet_t *outp,
+ int totalParms, int totalData);
+
+extern void smb_FreeTran2Packet(smb_tran2Packet_t *t2p);
+
+extern void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp);
+
extern long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
extern long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
--- /dev/null
+/*
+ * Copyright (c) 2009 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define SMB_RPC_IMPL
+
+#include <afs/param.h>
+#include <afs/stds.h>
+
+#include <windows.h>
+#pragma warning(push)
+#pragma warning(disable: 4005)
+#include <ntstatus.h>
+#pragma warning(pop)
+#include <stdlib.h>
+#include <string.h>
+#include <osi.h>
+
+#include "afsd.h"
+#include "smb.h"
+
+#include <strsafe.h>
+
+/**
+ Meant to set up an endpoing by name, but only checks for a valid name
+
+ We don't bother trying to locate the endpoint here because the RPC
+ logic already does that using much more specific information than
+ just the name.
+
+ */
+afs_int32
+smb_RPC_SetupEndpointByname(smb_rpc_t * rpcp, const clientchar_t * epnamep)
+{
+ const char * secondary_name = NULL;
+
+ if (!cm_ClientStrCmpI(epnamep, _C("wkssvc"))) {
+ secondary_name = ".\\PIPE\\wkssvc";
+ } else if (!cm_ClientStrCmpI(epnamep, _C("srvsvc"))) {
+ secondary_name = ".\\PIPE\\srvsvc";
+ } else {
+ return CM_ERROR_NOSUCHPATH;
+ }
+
+ return MSRPC_InitConn(&rpcp->rpc_conn, secondary_name);
+}
+
+/**
+ Setup a smb_fid:: structure for RPC
+
+ \note Obtains fidp->mx */
+afs_int32
+smb_SetupRPCFid(smb_fid_t * fidp, const clientchar_t * _epnamep,
+ unsigned short * file_type,
+ unsigned short * device_state)
+{
+ smb_rpc_t *rpcp;
+ afs_int32 code = 0;
+ const clientchar_t * epnamep;
+
+ epnamep = cm_ClientStrChr(_epnamep, _C('\\'));
+ if (epnamep == NULL)
+ epnamep = _epnamep;
+ else
+ epnamep = cm_ClientCharNext(epnamep);
+
+ lock_ObtainMutex(&fidp->mx);
+ fidp->flags |= SMB_FID_RPC;
+ fidp->scp = &cm_data.fakeSCache;
+ cm_HoldSCache(fidp->scp);
+ if (fidp->rpcp == NULL) {
+ rpcp = malloc(sizeof(*rpcp));
+ memset(rpcp, 0, sizeof(*rpcp));
+ fidp->rpcp = rpcp;
+ rpcp->fidp = fidp;
+ } else {
+ rpcp = fidp->rpcp;
+ }
+ code = smb_RPC_SetupEndpointByname(rpcp, epnamep);
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (code == 0) {
+ *file_type = SMB_FILETYPE_MESSAGE_MODE_PIPE;
+ *device_state =((0xff) | /* instance count */
+ SMB_DEVICESTATE_READMSGFROMPIPE |
+ SMB_DEVICESTATE_MESSAGEMODEPIPE |
+ SMB_DEVICESTATE_PIPECLIENTEND);
+ }
+
+ return code;
+}
+
+/**
+ Cleanup a smb_fid:: structure that was used for RPC
+
+ \note Called with fidp->mx locked */
+void
+smb_CleanupRPCFid(smb_fid_t * fidp)
+{
+ if (fidp->rpcp)
+ MSRPC_FreeConn(&fidp->rpcp->rpc_conn);
+}
+
+afs_int32
+smb_RPC_PrepareRead(smb_rpc_t * rpcp)
+{
+ return MSRPC_PrepareRead(&rpcp->rpc_conn);
+}
+
+afs_int32
+smb_RPC_PrepareWrite(smb_rpc_t * rpcp)
+{
+ return 0;
+}
+
+afs_int32
+smb_RPC_ReadPacketLength(smb_rpc_t * rpcp, afs_uint32 max_length)
+{
+ return MSRPC_ReadMessageLength(&rpcp->rpc_conn, max_length);
+}
+
+afs_int32
+smb_RPC_ReadPacket(smb_rpc_t * rpcp, BYTE * buffer, afs_uint32 length)
+{
+ osi_Log1(smb_logp, " RPC Read Packet for length %d", length);
+ return MSRPC_ReadMessage(&rpcp->rpc_conn, buffer, length);
+}
+
+afs_int32
+smb_RPC_WritePacket(smb_rpc_t * rpcp, BYTE * buffer, afs_uint32 length,
+ cm_user_t * userp)
+{
+ return MSRPC_WriteMessage(&rpcp->rpc_conn, buffer, length, userp);
+}
+
+/*! \brief Begin an RPC operation
+
+ While generally we receive RPC requests one at a time, we have to
+ protect against receiving multiple requests in parallel since
+ there's nothing really preventing that from happening.
+
+ This should be called before calling any of the smb_RPC_*()
+ functions. If the return value is non-zero, it should be considered
+ unsafe to call any smb_RPC_*() function.
+
+ Each successful call to smb_RPC_BeginOp() should be coupled with a
+ call to smb_RPC_EndOp().
+
+ \note Should be called with rpcp->fidp->mx locked.
+ */
+afs_int32
+smb_RPC_BeginOp(smb_rpc_t * rpcp)
+{
+ if (rpcp == NULL)
+ return CM_ERROR_INVAL;
+
+ osi_assertx(rpcp->fidp, "No fidp assigned to smb_rpc_t");
+ lock_AssertMutex(&rpcp->fidp->mx);
+
+ while (rpcp->fidp->flags & SMB_FID_RPC_INCALL) {
+ osi_SleepM((LONG_PTR) rpcp, &rpcp->fidp->mx);
+ lock_ObtainMutex(&rpcp->fidp->mx);
+ }
+
+ rpcp->fidp->flags |= SMB_FID_RPC_INCALL;
+ return 0;
+}
+
+/*! \brief End an RPC operation
+
+ \see smb_RPC_BeginOp()
+ */
+afs_int32
+smb_RPC_EndOp(smb_rpc_t * rpcp)
+{
+ lock_ObtainMutex(&rpcp->fidp->mx);
+ osi_assertx(rpcp->fidp->flags & SMB_FID_RPC_INCALL, "RPC_EndOp() call without RPC_BeginOp()");
+ rpcp->fidp->flags &= ~SMB_FID_RPC_INCALL;
+ lock_ReleaseMutex(&rpcp->fidp->mx);
+
+ osi_Wakeup((LONG_PTR) rpcp);
+
+ return 0;
+}
+
+/**
+ Handle a SMB_COM_READ for an RPC fid
+
+ Called from smb_ReceiveCoreRead when we receive a read on the RPC
+ fid */
+afs_int32
+smb_RPCRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+ smb_rpc_t *rpcp;
+ long count;
+ char *op;
+ afs_int32 code;
+ cm_user_t *userp;
+
+ count = smb_GetSMBParm(inp, 1);
+ userp = smb_GetUserFromVCP(vcp, inp);
+
+ osi_Log3(smb_logp, "smb_RPCRead for user[0x%p] fid[0x%p (%d)]",
+ userp, fidp, fidp->fid);
+
+ lock_ObtainMutex(&fidp->mx);
+ rpcp = fidp->rpcp;
+ code = smb_RPC_BeginOp(rpcp);
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (code) {
+ cm_ReleaseUser(userp);
+
+ return code;
+ }
+
+ code = smb_RPC_PrepareRead(rpcp);
+
+ if (code) {
+ cm_ReleaseUser(userp);
+
+ smb_RPC_EndOp(rpcp);
+
+ return code;
+ }
+
+ count = smb_RPC_ReadPacketLength(rpcp, count);
+
+ /* now set the parms for a read of count bytes */
+ smb_SetSMBParm(outp, 0, count);
+ smb_SetSMBParm(outp, 1, 0);
+ smb_SetSMBParm(outp, 2, 0);
+ smb_SetSMBParm(outp, 3, 0);
+ smb_SetSMBParm(outp, 4, 0);
+
+ smb_SetSMBDataLength(outp, count+3);
+
+ op = smb_GetSMBData(outp, NULL);
+ *op++ = 1;
+ *op++ = (char)(count & 0xff);
+ *op++ = (char)((count >> 8) & 0xff);
+
+ smb_RPC_ReadPacket(rpcp, op, count);
+
+ smb_RPC_EndOp(rpcp);
+
+ cm_ReleaseUser(userp);
+
+ return 0;
+}
+
+/**
+ Handle SMB_COM_WRITE for an RPC fid
+
+ Called from smb_ReceiveCoreWrite when we receive a write call on
+ the RPC file descriptor.
+ */
+afs_int32
+smb_RPCWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+ smb_rpc_t *rpcp;
+ long count;
+ afs_int32 code;
+ char *op;
+ int inDataBlockCount;
+ cm_user_t *userp = NULL;
+
+ code = 0;
+ count = smb_GetSMBParm(inp, 1);
+ userp = smb_GetUserFromVCP(vcp, inp);
+
+ osi_Log3(smb_logp, "smb_RPCWrite for user[0x%p] fid[0x%p (%d)]",
+ userp, fidp, fidp->fid);
+
+ if (userp == NULL) {
+ code = CM_ERROR_BADSMB;
+ goto done;
+ }
+
+ lock_ObtainMutex(&fidp->mx);
+ rpcp = fidp->rpcp;
+ code = smb_RPC_BeginOp(rpcp);
+ lock_ReleaseMutex(&fidp->mx);
+ if (code)
+ goto done;
+
+ smb_RPC_PrepareWrite(rpcp);
+
+ op = smb_GetSMBData(inp, NULL);
+ op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
+
+ code = smb_RPC_WritePacket(rpcp, op, count, userp);
+
+ smb_RPC_EndOp(rpcp);
+
+ done:
+ /* return # of bytes written */
+ if (code == 0) {
+ smb_SetSMBParm(outp, 0, count);
+ smb_SetSMBDataLength(outp, 0);
+ }
+
+ if (userp)
+ cm_ReleaseUser(userp);
+
+ return code;
+}
+
+/**
+ Handle SMB_COM_WRITE_ANDX for an RPC fid
+
+ Called from smb_ReceiveV3WriteX when we receive a write call on the
+ RPC file descriptor.
+ */
+afs_int32
+smb_RPCV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+ smb_rpc_t *rpcp;
+ long count;
+ afs_int32 code;
+ char *op;
+ cm_user_t *userp = NULL;
+
+ code = 0;
+ count = smb_GetSMBParm(inp, 10);
+ userp = smb_GetUserFromVCP(vcp, inp);
+
+ osi_Log3(smb_logp, "smb_RPCV3Write for user[0x%p] fid[0x%p (%d)]",
+ userp, fidp, fidp->fid);
+
+ if (userp == NULL) {
+ code = CM_ERROR_BADSMB;
+ goto done;
+ }
+
+ lock_ObtainMutex(&fidp->mx);
+ rpcp = fidp->rpcp;
+ code = smb_RPC_BeginOp(rpcp);
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (code)
+ goto done;
+
+ smb_RPC_PrepareWrite(rpcp);
+
+ op = inp->data + smb_GetSMBParm(inp, 11);
+
+ code = smb_RPC_WritePacket(rpcp, op, count, userp);
+
+ smb_RPC_EndOp(rpcp);
+
+ done:
+ /* return # of bytes written */
+ if (code == 0) {
+ smb_SetSMBParm(outp, 2, count);
+ smb_SetSMBParm(outp, 3, 0); /* reserved */
+ smb_SetSMBParm(outp, 4, 0); /* reserved */
+ smb_SetSMBParm(outp, 5, 0); /* reserved */
+ smb_SetSMBDataLength(outp, 0);
+ }
+
+ if (userp)
+ cm_ReleaseUser(userp);
+
+ return code;
+}
+
+
+/**
+ Handle SMB_COM_READ_ANDX for an RPC fid
+
+ Called from smb_ReceiveV3ReadX to handle RPC descriptor reads */
+afs_int32
+smb_RPCV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+ smb_rpc_t *rpcp;
+ long count;
+ afs_int32 code;
+ char *op;
+ cm_user_t *userp;
+ smb_user_t *uidp;
+
+ count = smb_GetSMBParm(inp, 5);
+
+ uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+ if (!uidp)
+ return CM_ERROR_BADSMB;
+ userp = smb_GetUserFromUID(uidp);
+ osi_assertx(userp != NULL, "null cm_user_t");
+
+ osi_Log3(smb_logp, "smb_RPCV3Read for user[0x%p] fid[0x%p (%d)]",
+ userp, fidp, fidp->fid);
+
+ if (uidp && uidp->unp) {
+ osi_Log3(afsd_logp, "RPC uid %d user %x name %S",
+ uidp->userID, userp,
+ osi_LogSaveClientString(afsd_logp, uidp->unp->name));
+ } else {
+ if (uidp)
+ osi_Log2(afsd_logp, "RPC uid %d user %x no name",
+ uidp->userID, userp);
+ else
+ osi_Log1(afsd_logp, "RPC no uid user %x no name",
+ userp);
+ }
+
+ lock_ObtainMutex(&fidp->mx);
+ rpcp = fidp->rpcp;
+ code = smb_RPC_BeginOp(rpcp);
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (code) {
+ if (uidp)
+ smb_ReleaseUID(uidp);
+ cm_ReleaseUser(userp);
+ return code;
+ }
+
+ code = smb_RPC_PrepareRead(rpcp);
+ if (uidp) {
+ smb_ReleaseUID(uidp);
+ }
+ if (code) {
+ cm_ReleaseUser(userp);
+ smb_RPC_EndOp(rpcp);
+ return code;
+ }
+
+ count = smb_RPC_ReadPacketLength(rpcp, count);
+
+ /* 0 and 1 are reserved for request chaining, were setup by our caller,
+ * and will be further filled in after we return.
+ */
+ smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
+ smb_SetSMBParm(outp, 3, 0); /* resvd */
+ smb_SetSMBParm(outp, 4, 0); /* resvd */
+ smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
+ /* fill in #6 when we have all the parameters' space reserved */
+ smb_SetSMBParm(outp, 7, 0); /* resv'd */
+ smb_SetSMBParm(outp, 8, 0); /* resv'd */
+ smb_SetSMBParm(outp, 9, 0); /* resv'd */
+ smb_SetSMBParm(outp, 10, 0); /* resv'd */
+ smb_SetSMBParm(outp, 11, 0); /* reserved */
+
+ /* get op ptr after putting in the last parm, since otherwise we don't
+ * know where the data really is.
+ */
+ op = smb_GetSMBData(outp, NULL);
+
+ /* now fill in offset from start of SMB header to first data byte (to op) */
+ smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
+
+ /* set the packet data length the count of the # of bytes */
+ smb_SetSMBDataLength(outp, count);
+
+ smb_RPC_ReadPacket(rpcp, op, count);
+
+ smb_RPC_EndOp(rpcp);
+
+ /* and cleanup things */
+ cm_ReleaseUser(userp);
+
+ return 0;
+}
+
+afs_int32
+smb_RPCNmpipeTransact(smb_fid_t *fidp, smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+ smb_tran2Packet_t *outp = NULL;
+ struct smb_rpc *rpcp;
+ afs_int32 code = 0;
+ cm_user_t * userp = NULL;
+ smb_user_t * uidp = NULL;
+ int len;
+
+ osi_Log0(smb_logp, "smb_RPCNmpipeTransact() begin");
+
+ uidp = smb_FindUID(vcp, p->uid, 0);
+ if (!uidp)
+ return CM_ERROR_BADSMB;
+ userp = smb_GetUserFromUID(uidp);
+ osi_assertx(userp != NULL, "null cm_user_t");
+
+ if (uidp && uidp->unp) {
+ osi_Log3(afsd_logp, "RPC Transact uid %d user %x name %S",
+ uidp->userID, userp,
+ osi_LogSaveClientString(afsd_logp, uidp->unp->name));
+ } else {
+ if (uidp)
+ osi_Log2(afsd_logp, "RPC Transact uid %d user %x no name",
+ uidp->userID, userp);
+ else
+ osi_Log1(afsd_logp, "RPC Transact no uid user %x no name",
+ userp);
+ }
+
+ lock_ObtainMutex(&fidp->mx);
+ rpcp = fidp->rpcp;
+ code = smb_RPC_BeginOp(rpcp);
+
+ if (code) {
+ osi_Log0(smb_logp, "Can't begin RPC op. Aborting");
+ lock_ReleaseMutex(&fidp->mx);
+
+ smb_ReleaseUID(uidp);
+ cm_ReleaseUser(userp);
+ return code;
+ }
+
+ osi_assertx((fidp->flags & SMB_FID_RPC), "FID wasn't setup for RPC");
+ osi_assertx(fidp->rpcp, "smb_rpc_t not associated with RPC FID");
+
+ lock_ReleaseMutex(&fidp->mx);
+
+ code = smb_RPC_PrepareWrite(rpcp);
+ if (code)
+ goto done;
+
+ code = smb_RPC_WritePacket(rpcp, p->datap, p->totalData, userp);
+ if (code)
+ goto done;
+
+ code = smb_RPC_PrepareRead(rpcp);
+ if (code)
+ goto done;
+
+ len = smb_RPC_ReadPacketLength(rpcp, p->maxReturnData);
+
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, len);
+ if (len > 0) {
+ code = smb_RPC_ReadPacket(rpcp, outp->datap, len);
+
+ if (code == CM_ERROR_RPC_MOREDATA) {
+ outp->error_code = CM_ERROR_RPC_MOREDATA;
+ }
+ }
+
+ if (code == 0 || code == CM_ERROR_RPC_MOREDATA)
+ smb_SendTran2Packet(vcp, outp, op);
+ smb_FreeTran2Packet(outp);
+
+ done:
+ smb_RPC_EndOp(rpcp);
+
+ osi_Log1(smb_logp, "smb_RPCNmpipeTransact() end code=%d", code);
+
+ if (uidp)
+ smb_ReleaseUID(uidp);
+ if (userp)
+ cm_ReleaseUser(userp);
+
+ return code;
+}
--- /dev/null
+/*
+ * Copyright (c) 2009 Secure Endpoints Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __SMB_RPC_H__
+#define __SMB_RPC_H__
+
+struct smb_rpc;
+
+#ifdef SMB_RPC_IMPL
+
+#include "msrpc.h"
+
+typedef
+struct smb_rpc {
+ smb_fid_t * fidp;
+ msrpc_conn rpc_conn;
+} smb_rpc_t;
+
+#endif
+
+afs_int32
+smb_SetupRPCFid(smb_fid_t * fidp, const clientchar_t * epnamep,
+ unsigned short * file_type,
+ unsigned short * device_state);
+
+void
+smb_CleanupRPCFid(IN smb_fid_t * fidp);
+
+afs_int32
+smb_RPCRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
+
+afs_int32
+smb_RPCWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
+
+afs_int32
+smb_RPCV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
+
+afs_int32
+smb_RPCV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
+
+afs_int32
+smb_RPCNmpipeTransact(smb_fid_t *fidp, smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op);
+
+#endif /* __SMB_RPC_H__ */
!ENDIF
$(VERSFILE).c:
- echo char $(CML_PREFIX)cml_version_number[]="@(#)OpenAFS_$(AFSPRODUCT_VERSION)"; >$(VERSFILE).c
- echo char* AFSVersion = "OpenAFS_$(AFSPRODUCT_VERSION)"; >>$(VERSFILE).c
+ echo #include "wchar.h" >$(VERSFILE).c
+ echo unsigned char $(CML_PREFIX)cml_version_number[]="@(#)OpenAFS_$(AFSPRODUCT_VERSION)"; >>$(VERSFILE).c
+ echo unsigned char* AFSVersion = "OpenAFS_$(AFSPRODUCT_VERSION)"; >>$(VERSFILE).c
+ echo wchar_t w$(CML_PREFIX)cml_version_number[]=L"@(#)OpenAFS_$(AFSPRODUCT_VERSION)"; >>$(VERSFILE).c
+ echo wchar_t* wAFSVersion = L"OpenAFS_$(AFSPRODUCT_VERSION)"; >>$(VERSFILE).c
$(VERSFILE).h:
echo #define AFS_VERINFO_BUILD "OpenAFS_$(AFSPRODUCT_VERSION)" >$(VERSFILE).h
echo #define AFS_VERINFO_FILEVER $(AFSPRODUCT_FILE_VERSION) >>$(VERSFILE).h
echo #define AFSPRODUCT_VERSION "$(AFSPRODUCT_VERSION)" >> $(VERSFILE).h
+ echo #define AFSPRODUCT_VERSION_MAJOR $(AFSPRODUCT_VER_MAJOR) >> $(VERSFILE).h
+ echo #define AFSPRODUCT_VERSION_MINOR $(AFSPRODUCT_VER_MINOR) >> $(VERSFILE).h
+ echo #define AFSPRODUCT_VERSION_PATCH $(AFSPRODUCT_VER_PATCH) >> $(VERSFILE).h
+ echo #define AFSPRODUCT_VERSION_BUILD $(AFSPRODUCT_VER_BUILD) >> $(VERSFILE).h
+ echo #ifdef AFS_VERSION_STRINGS >> $(VERSFILE).h
+ echo extern unsigned char $(CML_PREFIX)cml_version_number[]; >> $(VERSFILE).h
+ echo extern unsigned char* AFSVersion; >> $(VERSFILE).h
+ echo extern wchar_t w$(CML_PREFIX)cml_version_number[]; >> $(VERSFILE).h
+ echo extern wchar_t* wAFSVersion; >> $(VERSFILE).h
+ echo #endif >> $(VERSFILE).h
$(VERSFILE).txt:
echo OpenAFS_$(AFSPRODUCT_VERSION)>$(VERSFILE).txt