#include "includes.h"
-extern int Protocol;
+extern enum protocol_types Protocol;
extern int smb_read_error;
extern int global_oplock_break;
-extern BOOL case_sensitive;
-extern BOOL case_preserve;
-extern BOOL short_case_preserve;
extern struct current_user current_user;
static const char *known_nt_pipes[] = {
"\\spoolss",
"\\netdfs",
"\\rpcecho",
- "\\epmapper",
+ "\\svcctl",
+ "\\eventlog",
NULL
};
if (ptr==NULL)
smb_panic("nttrans_realloc() called with NULL ptr\n");
- tptr = Realloc_zero(*ptr, size);
+ tptr = SMB_REALLOC(*ptr, size);
if(tptr == NULL) {
*ptr = NULL;
return NULL;
}
+ memset(tptr,'\0',size);
*ptr = tptr;
Save case semantics.
****************************************************************************/
-static void set_posix_case_semantics(uint32 file_attributes)
+static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
{
if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS))
return;
- saved_case_sensitive = case_sensitive;
- saved_case_preserve = case_preserve;
- saved_short_case_preserve = short_case_preserve;
+ saved_case_sensitive = conn->case_sensitive;
+ saved_case_preserve = conn->case_preserve;
+ saved_short_case_preserve = conn->short_case_preserve;
/* Set to POSIX. */
- case_sensitive = True;
- case_preserve = True;
- short_case_preserve = True;
+ conn->case_sensitive = True;
+ conn->case_preserve = True;
+ conn->short_case_preserve = True;
}
/****************************************************************************
Restore case semantics.
****************************************************************************/
-static void restore_case_semantics(uint32 file_attributes)
+static void restore_case_semantics(connection_struct *conn, uint32 file_attributes)
{
if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS))
return;
- case_sensitive = saved_case_sensitive;
- case_preserve = saved_case_preserve;
- short_case_preserve = saved_short_case_preserve;
+ conn->case_sensitive = saved_case_sensitive;
+ conn->case_preserve = saved_case_preserve;
+ conn->short_case_preserve = saved_short_case_preserve;
}
/****************************************************************************
uint32 *desired_access, uint32 share_access, uint32 file_attributes)
{
int smb_open_mode = -1;
+ uint32 original_desired_access = *desired_access;
+
+ /* This is a nasty hack - must fix... JRA. */
+ if (*desired_access == MAXIMUM_ALLOWED_ACCESS) {
+ *desired_access = FILE_GENERIC_ALL;
+ }
/*
* Convert GENERIC bits to specific bits.
DEBUG(10,("map_share_mode: FILE_SHARE_DELETE requested. open_mode = 0x%x\n", smb_open_mode));
}
+ if(*desired_access & DELETE_ACCESS) {
+ DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode));
+ }
+
/*
* We need to store the intent to open for Delete. This
* is what determines if a delete on close flag can be set.
* is the only practical way. JRA.
*/
- if(*desired_access & DELETE_ACCESS) {
- DEBUG(10,("map_share_mode: DELETE_ACCESS requested. open_mode = 0x%x\n", smb_open_mode));
- }
-
if (create_options & FILE_DELETE_ON_CLOSE) {
+ /*
+ * W2K3 bug compatibility mode... To set delete on close
+ * the redirector must have *specifically* set DELETE_ACCESS
+ * in the desired_access field. Just asking for GENERIC_ALL won't do. JRA.
+ */
+
+ if (!(original_desired_access & DELETE_ACCESS)) {
+ DEBUG(5,("map_share_mode: FILE_DELETE_ON_CLOSE requested without \
+DELETE_ACCESS for file %s. (desired_access = 0x%lx)\n",
+ fname, (unsigned long)*desired_access));
+ return -1;
+ }
/* Implicit delete access is *NOT* requested... */
smb_open_mode |= DELETE_ON_CLOSE_FLAG;
DEBUG(10,("map_share_mode: FILE_DELETE_ON_CLOSE requested. open_mode = 0x%x\n", smb_open_mode));
int ret;
int pnum = -1;
char *p = NULL;
- NTSTATUS status;
- srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
- if (!NT_STATUS_IS_OK(status))
- return ERROR_NT(status);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
return ret;
SMB_BIG_UINT allocation_size = 0;
int smb_ofun;
int smb_open_mode;
- int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
/* Breakout the oplock request bits so we can set the
reply bits separately. */
int oplock_request = 0;
- mode_t unixmode;
int fmode=0,rmode=0;
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
END_PROFILE(SMBntcreateX);
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
/*
/*
* This filename is relative to a directory fid.
*/
+ pstring rel_fname;
files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid);
size_t dir_name_len;
if(!dir_fsp->is_directory) {
- srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
-
/*
we need to handle the case when we get a
relative open relative to a file and the
pathname is blank - this is a reopen!
(hint from demyn plantenberg)
*/
-
END_PROFILE(SMBntcreateX);
return(ERROR_DOS(ERRDOS,ERRbadfid));
*/
if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') {
- pstrcat(fname, "\\");
+ pstrcat(fname, "/");
dir_name_len++;
}
- srvstr_get_path(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE,&status);
+ srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status,False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
+ pstrcat(fname, rel_fname);
} else {
- srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status,False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
share_access,
file_attributes)) == -1) {
END_PROFILE(SMBntcreateX);
- return ERROR_DOS(ERRDOS,ERRnoaccess);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
* Check if POSIX semantics are wanted.
*/
- set_posix_case_semantics(file_attributes);
+ set_posix_case_semantics(conn, file_attributes);
unix_convert(fname,conn,0,&bad_path,&sbuf);
-
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-
+
+ /* FAKE_FILE is a special case */
+ if (fake_file_type == FAKE_FILE_TYPE_NONE) {
+ /* Normal file. */
+ if (bad_path) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
+ /* All file access must go through check_name() */
+ if (!check_name(fname,conn)) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ }
+ }
+
+#if 0
+ /* This is the correct thing to do (check every time) but can_delete is
+ expensive (it may have to read the parent directory permissions). So
+ for now we're not doing it unless we have a strong hint the client
+ is really going to delete this file. */
+ if (desired_access & DELETE_ACCESS) {
+#else
+ /* Setting FILE_SHARE_DELETE is the hint. */
+ if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) {
+#endif
+ status = can_delete(conn, fname, file_attributes, bad_path, True);
+ /* We're only going to fail here if it's access denied, as that's the
+ only error we care about for "can we delete this ?" questions. */
+ if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(status);
+ }
+ }
+
/*
* If it's a request for a directory open, deal with it separately.
*/
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
- restore_case_semantics(file_attributes);
+ restore_case_semantics(conn, file_attributes);
if(!fsp) {
END_PROFILE(SMBntcreateX);
fsp = open_file_shared1(conn,fname,&sbuf,
desired_access,
smb_open_mode,
- smb_ofun,unixmode, oplock_request,
+ smb_ofun,file_attributes,oplock_request,
&rmode,&smb_action);
} else {
/* to open a fake_file --metze */
fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf,
desired_access,
smb_open_mode,
- smb_ofun,unixmode, oplock_request,
+ smb_ofun,file_attributes, oplock_request,
&rmode,&smb_action);
}
*/
if (create_options & FILE_NON_DIRECTORY_FILE) {
- restore_case_semantics(file_attributes);
+ restore_case_semantics(conn, file_attributes);
SSVAL(outbuf, smb_flg2,
SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
END_PROFILE(SMBntcreateX);
}
oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
- restore_case_semantics(file_attributes);
+ restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
} else {
- restore_case_semantics(file_attributes);
+ restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ clear_cached_errors();
+ return -1;
+ }
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
}
}
- restore_case_semantics(file_attributes);
+ restore_case_semantics(conn, file_attributes);
file_len = sbuf.st_size;
fmode = dos_mode(conn,fname,&sbuf);
allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
#endif
if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) {
- fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
+ if (fsp->is_directory) {
+ close_file(fsp,False);
+ END_PROFILE(SMBntcreateX);
+ /* Can't set allocation size on a directory. */
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+ }
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
close_file(fsp,False);
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
} else {
- fsp->initial_allocation_size = SMB_ROUNDUP(((SMB_BIG_UINT)file_len),SMB_ROUNDUP_ALLOCATION_SIZE);
+ fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len);
}
/*
p += 8;
SIVAL(p,0,fmode); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
+ SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
p += 8;
SOFF_T(p,0,file_len);
- p += 12;
+ p += 8;
+ if (flags & EXTENDED_RESPONSE_REQUIRED)
+ SSVAL(p,2,0x7);
+ p += 4;
SCVAL(p,0,fsp->is_directory ? 1 : 0);
-
+
DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
result = chain_reply(inbuf,outbuf,length,bufsize);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
- status = check_path_syntax(fname);
+ srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
TALLOC_CTX *mem_ctx;
BOOL ret;
- if (sd_len == 0) {
+ if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) {
return NT_STATUS_OK;
}
return NT_STATUS_OK;
}
+/****************************************************************************
+ Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
+****************************************************************************/
+
+static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
+{
+ struct ea_list *ea_list_head = NULL;
+ size_t offset = 0;
+
+ if (data_size < 4) {
+ return NULL;
+ }
+
+ while (offset + 4 <= data_size) {
+ size_t next_offset = IVAL(pdata,offset);
+ struct ea_list *tmp;
+ struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL);
+
+ DLIST_ADD_END(ea_list_head, eal, tmp);
+ if (next_offset == 0) {
+ break;
+ }
+ offset += next_offset;
+ }
+
+ return ea_list_head;
+}
+
/****************************************************************************
Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
****************************************************************************/
static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
char **ppsetup, uint32 setup_count,
char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count)
+ char **ppdata, uint32 data_count, uint32 max_data_count)
{
pstring fname;
char *params = *ppparams;
char *data = *ppdata;
/* Breakout the oplock request bits so we can set the reply bits separately. */
int oplock_request = 0;
- mode_t unixmode;
int fmode=0,rmode=0;
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
uint32 create_disposition;
uint32 create_options;
uint32 sd_len;
+ uint32 ea_len;
uint16 root_dir_fid;
SMB_BIG_UINT allocation_size = 0;
int smb_ofun;
int smb_open_mode;
- int smb_attr;
time_t c_time;
- NTSTATUS nt_status;
+ struct ea_list *ea_list = NULL;
+ TALLOC_CTX *ctx = NULL;
+ char *pdata = NULL;
+ NTSTATUS status;
DEBUG(5,("call_nt_transact_create\n"));
if(parameter_count < 54) {
DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
- return ERROR_DOS(ERRDOS,ERRnoaccess);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
flags = IVAL(params,0);
create_disposition = IVAL(params,28);
create_options = IVAL(params,32);
sd_len = IVAL(params,36);
+ ea_len = IVAL(params,40);
root_dir_fid = (uint16)IVAL(params,4);
- smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
+
+ /* Ensure the data_len is correct for the sd and ea values given. */
+ if ((ea_len + sd_len > data_count) ||
+ (ea_len > data_count) || (sd_len > data_count) ||
+ (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) {
+ DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n",
+ (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count ));
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (ea_len) {
+ if (!lp_ea_support(SNUM(conn))) {
+ DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n",
+ (unsigned int)ea_len ));
+ return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
+ }
+
+ if (ea_len < 10) {
+ DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n",
+ (unsigned int)ea_len ));
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ }
if (create_options & FILE_OPEN_BY_FILE_ID) {
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
* NT values, as that's what our code is structured to accept.
*/
- if((smb_ofun = map_create_disposition( create_disposition )) == -1)
- return ERROR_DOS(ERRDOS,ERRbadmem);
+ if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
/*
* Get the file name.
/*
* This filename is relative to a directory fid.
*/
-
files_struct *dir_fsp = file_fsp(params,4);
size_t dir_name_len;
return ERROR_DOS(ERRDOS,ERRbadfid);
if(!dir_fsp->is_directory) {
-
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
- nt_status = check_path_syntax(fname);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return ERROR_NT(nt_status);
+ srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
/*
*/
if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
- pstrcat(fname, "\\");
+ pstrcat(fname, "/");
dir_name_len++;
}
- srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len,
- parameter_count-53, STR_TERMINATE);
- nt_status = check_path_syntax(fname);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return ERROR_NT(nt_status);
+ {
+ pstring tmpname;
+ srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status, False);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+ pstrcat(fname, tmpname);
}
} else {
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE);
- nt_status = check_path_syntax(fname);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return ERROR_NT(nt_status);
+ srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status, False);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
}
/*
if((smb_open_mode = map_share_mode( fname, create_options, &desired_access,
share_access, file_attributes)) == -1)
- return ERROR_DOS(ERRDOS,ERRnoaccess);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
* Check if POSIX semantics are wanted.
*/
- set_posix_case_semantics(file_attributes);
+ set_posix_case_semantics(conn, file_attributes);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ restore_case_semantics(conn, file_attributes);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
+ /* All file access must go through check_name() */
+ if (!check_name(fname,conn)) {
+ restore_case_semantics(conn, file_attributes);
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ }
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-
+#if 0
+ /* This is the correct thing to do (check every time) but can_delete is
+ expensive (it may have to read the parent directory permissions). So
+ for now we're not doing it unless we have a strong hint the client
+ is really going to delete this file. */
+ if (desired_access & DELETE_ACCESS) {
+#else
+ /* Setting FILE_SHARE_DELETE is the hint. */
+ if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) {
+#endif
+ status = can_delete(conn, fname, file_attributes, bad_path, True);
+ /* We're only going to fail here if it's access denied, as that's the
+ only error we care about for "can we delete this ?" questions. */
+ if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(status);
+ }
+ }
+
+ if (ea_len) {
+ ctx = talloc_init("NTTRANS_CREATE_EA");
+ if (!ctx) {
+ talloc_destroy(ctx);
+ restore_case_semantics(conn, file_attributes);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ pdata = data + sd_len;
+
+ /* We have already checked that ea_len <= data_count here. */
+ ea_list = read_nttrans_ea_list(ctx, pdata, ea_len);
+ if (!ea_list ) {
+ talloc_destroy(ctx);
+ restore_case_semantics(conn, file_attributes);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ }
+
/*
* If it's a request for a directory open, deal with it separately.
*/
/* Can't open a temp directory. IFS kit test. */
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
+ talloc_destroy(ctx);
+ restore_case_semantics(conn, file_attributes);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
* CreateDirectory() call.
*/
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
- restore_case_semantics(file_attributes);
+ talloc_destroy(ctx);
+ restore_case_semantics(conn, file_attributes);
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
*/
fsp = open_file_shared1(conn,fname,&sbuf,desired_access,
- smb_open_mode,smb_ofun,unixmode,
+ smb_open_mode,smb_ofun,file_attributes,
oplock_request,&rmode,&smb_action);
if (!fsp) {
*/
if (create_options & FILE_NON_DIRECTORY_FILE) {
- restore_case_semantics(file_attributes);
+ restore_case_semantics(conn, file_attributes);
SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
- restore_case_semantics(file_attributes);
+ talloc_destroy(ctx);
+ restore_case_semantics(conn, file_attributes);
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
} else {
- restore_case_semantics(file_attributes);
+ talloc_destroy(ctx);
+ restore_case_semantics(conn, file_attributes);
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ clear_cached_errors();
+ return -1;
+ }
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
}
fmode = FILE_ATTRIBUTE_NORMAL;
if (fmode & aDIR) {
+ talloc_destroy(ctx);
close_file(fsp,False);
- restore_case_semantics(file_attributes);
- return ERROR_DOS(ERRDOS,ERRnoaccess);
+ restore_case_semantics(conn, file_attributes);
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
/*
* correct bit for extended oplock reply.
*/
- if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
extended_oplock_granted = True;
+ }
- if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
extended_oplock_granted = True;
+ }
}
/*
- * Now try and apply the desired SD.
+ * According to the MS documentation, the only time the security
+ * descriptor is applied to the opened file is iff we *created* the
+ * file; an existing file stays the same.
+ *
+ * Also, it seems (from observation) that you can open the file with
+ * any access mask but you can still write the sd. We need to override
+ * the granted access before we call set_sd
+ * Patch for bug #2242 from Tom Lackemann <cessnatomny@yahoo.com>.
*/
- if (sd_len && !NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
- close_file(fsp,False);
- restore_case_semantics(file_attributes);
- return ERROR_NT(nt_status);
- }
+ if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) {
+ uint32 saved_access = fsp->desired_access;
+
+ /* We have already checked that sd_len <= data_count here. */
+
+ fsp->desired_access = FILE_GENERIC_ALL;
+
+ status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_destroy(ctx);
+ close_file(fsp,False);
+ restore_case_semantics(conn, file_attributes);
+ return ERROR_NT(status);
+ }
+ fsp->desired_access = saved_access;
+ }
- restore_case_semantics(file_attributes);
+ if (ea_len && (smb_action == FILE_WAS_CREATED)) {
+ status = set_ea(conn, fsp, fname, ea_list);
+ talloc_destroy(ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ close_file(fsp,False);
+ restore_case_semantics(conn, file_attributes);
+ return ERROR_NT(status);
+ }
+ }
+
+ restore_case_semantics(conn, file_attributes);
/* Save the requested allocation size. */
allocation_size = (SMB_BIG_UINT)IVAL(params,12);
allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
#endif
if (allocation_size && (allocation_size > file_len)) {
- fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
+ if (fsp->is_directory) {
+ close_file(fsp,False);
+ END_PROFILE(SMBntcreateX);
+ /* Can't set allocation size on a directory. */
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+ }
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
close_file(fsp,False);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
} else {
- fsp->initial_allocation_size = SMB_ROUNDUP(((SMB_BIG_UINT)file_len),SMB_ROUNDUP_ALLOCATION_SIZE);
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len);
}
/* Realloc the size of parameters and data we will return */
p += 8;
SIVAL(p,0,fmode); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
+ SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
p += 8;
SOFF_T(p,0,file_len);
+ p += 8;
+ if (flags & EXTENDED_RESPONSE_REQUIRED)
+ SSVAL(p,2,0x7);
+ p += 4;
+ SCVAL(p,0,fsp->is_directory ? 1 : 0);
DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
return(-1);
}
+/****************************************************************************
+ Copy a file.
+****************************************************************************/
+
+static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint16 attrs)
+{
+ BOOL bad_path_oldname = False;
+ BOOL bad_path_newname = False;
+ SMB_STRUCT_STAT sbuf1, sbuf2;
+ pstring last_component_oldname;
+ pstring last_component_newname;
+ files_struct *fsp1,*fsp2;
+ uint16 fmode;
+ int access_mode;
+ int smb_action;
+ SMB_OFF_T ret=-1;
+ int close_ret;
+ NTSTATUS status = NT_STATUS_OK;
+
+ ZERO_STRUCT(sbuf1);
+ ZERO_STRUCT(sbuf2);
+
+ /* No wildcards. */
+ if (ms_has_wild(newname) || ms_has_wild(oldname)) {
+ return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+ }
+
+ if (!CAN_WRITE(conn))
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
+
+ unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
+ if (bad_path_oldname) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+
+ /* Quick check for "." and ".." */
+ if (last_component_oldname[0] == '.') {
+ if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ }
+
+ /* Source must already exist. */
+ if (!VALID_STAT(sbuf1)) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ if (!check_name(oldname,conn)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ /* Ensure attributes match. */
+ fmode = dos_mode(conn,oldname,&sbuf1);
+ if ((fmode & ~attrs) & (aHIDDEN | aSYSTEM))
+ return NT_STATUS_NO_SUCH_FILE;
+
+ unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
+ if (bad_path_newname) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+
+ /* Quick check for "." and ".." */
+ if (last_component_newname[0] == '.') {
+ if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ }
+
+ /* Disallow if newname already exists. */
+ if (VALID_STAT(sbuf2)) {
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ if (!check_name(newname,conn)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ /* No links from a directory. */
+ if (S_ISDIR(sbuf1.st_mode)) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
+ /* Ensure this is within the share. */
+ if (!reduce_name(conn, oldname) != 0) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
+
+ fsp1 = open_file_shared1(conn,oldname,&sbuf1,FILE_READ_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,
+ &access_mode,&smb_action);
+
+ if (!fsp1) {
+ status = NT_STATUS_ACCESS_DENIED;
+ if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+ status = NT_STATUS_SHARING_VIOLATION;
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
+ unix_ERR_ntstatus = NT_STATUS_OK;
+ return status;
+ }
+
+ fsp2 = open_file_shared1(conn,newname,&sbuf2,FILE_WRITE_DATA,SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
+ (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL),fmode,INTERNAL_OPEN_ONLY,
+ &access_mode,&smb_action);
+
+ if (!fsp2) {
+ status = NT_STATUS_ACCESS_DENIED;
+ if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+ status = NT_STATUS_SHARING_VIOLATION;
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
+ unix_ERR_ntstatus = NT_STATUS_OK;
+ close_file(fsp1,False);
+ return status;
+ }
+
+ if (sbuf1.st_size)
+ ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size);
+
+ /*
+ * As we are opening fsp1 read-only we only expect
+ * an error on close on fsp2 if we are out of space.
+ * Thus we don't look at the error return from the
+ * close of fsp1.
+ */
+ close_file(fsp1,False);
+
+ /* Ensure the modtime is set correctly on the destination file. */
+ fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
+
+ close_ret = close_file(fsp2,False);
+
+ /* Grrr. We have to do this as open_file_shared1 adds aARCH when it
+ creates the file. This isn't the correct thing to do in the copy case. JRA */
+ file_set_dosmode(conn, newname, fmode, &sbuf2, True);
+
+ if (ret < (SMB_OFF_T)sbuf1.st_size) {
+ return NT_STATUS_DISK_FULL;
+ }
+
+ if (close_ret != 0) {
+ status = map_nt_error_from_unix(close_ret);
+ DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
+ nt_errstr(status), oldname, newname));
+ }
+ return status;
+}
+
+/****************************************************************************
+ Reply to a NT rename request.
+****************************************************************************/
+
+int reply_ntrename(connection_struct *conn,
+ char *inbuf,char *outbuf,int length,int bufsize)
+{
+ int outsize = 0;
+ pstring oldname;
+ pstring newname;
+ char *p;
+ NTSTATUS status;
+ uint16 attrs = SVAL(inbuf,smb_vwv0);
+ uint16 rename_type = SVAL(inbuf,smb_vwv1);
+
+ START_PROFILE(SMBntrename);
+
+ p = smb_buf(inbuf) + 1;
+ p += srvstr_get_path(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, True);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBntrename);
+ return ERROR_NT(status);
+ }
+
+ if( strchr_m(oldname, ':')) {
+ /* Can't rename a stream. */
+ END_PROFILE(SMBntrename);
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+ }
+
+ if (ms_has_wild(oldname)) {
+ END_PROFILE(SMBntrename);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
+ }
+
+ p++;
+ p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, False);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBntrename);
+ return ERROR_NT(status);
+ }
+
+ RESOLVE_DFSPATH(oldname, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+
+ DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
+
+ switch(rename_type) {
+ case RENAME_FLAG_RENAME:
+ status = rename_internals(conn, oldname, newname, attrs, False);
+ break;
+ case RENAME_FLAG_HARD_LINK:
+ status = hardlink_internals(conn, oldname, newname);
+ break;
+ case RENAME_FLAG_COPY:
+ status = copy_internals(conn, oldname, newname, attrs);
+ break;
+ case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
+ status = NT_STATUS_INVALID_PARAMETER;
+ break;
+ default:
+ status = NT_STATUS_ACCESS_DENIED; /* Default error. */
+ break;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBntrename);
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ clear_cached_errors();
+ return -1;
+ }
+ return ERROR_NT(status);
+ }
+
+ /*
+ * Win2k needs a changenotify request response before it will
+ * update after a rename..
+ */
+ process_pending_change_notify_queue((time_t)0);
+ outsize = set_message(outbuf,0,0,True);
+
+ END_PROFILE(SMBntrename);
+ return(outsize);
+}
+
/****************************************************************************
Reply to an unsolicited SMBNTtranss - just ignore it!
****************************************************************************/
static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
char **ppsetup, uint32 setup_count,
char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count)
+ char **ppdata, uint32 data_count, uint32 max_data_count)
{
char *setup = *ppsetup;
files_struct *fsp;
static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
char **ppsetup, uint32 setup_count,
char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count)
+ char **ppdata, uint32 data_count, uint32 max_data_count)
{
char *params = *ppparams;
pstring new_name;
fsp = file_fsp(params, 0);
replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
CHECK_FSP(fsp, conn);
- srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE);
- status = check_path_syntax(new_name);
+ srvstr_get_path(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE, &status, True);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = rename_internals(conn, fsp->fsp_name,
- new_name, replace_if_exists);
+ new_name, 0, replace_if_exists);
if (!NT_STATUS_IS_OK(status))
return ERROR_NT(status);
static int call_nt_transact_query_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
char **ppsetup, uint32 setup_count,
char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count)
+ char **ppdata, uint32 data_count, uint32 max_data_count)
{
- uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
char *params = *ppparams;
char *data = *ppdata;
prs_struct pd;
static int call_nt_transact_set_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
char **ppsetup, uint32 setup_count,
char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count)
+ char **ppdata, uint32 data_count, uint32 max_data_count)
{
char *params= *ppparams;
char *data = *ppdata;
static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
char **ppsetup, uint32 setup_count,
char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count)
+ char **ppdata, uint32 data_count, uint32 max_data_count)
{
uint32 function;
uint16 fidnum;
* Allocate the correct amount and return the pointer to let
* it be deallocated when we return.
*/
- uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
SHADOW_COPY_DATA *shadow_data = NULL;
TALLOC_CTX *shadow_mem_ctx = NULL;
BOOL labels = False;
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- shadow_data = (SHADOW_COPY_DATA *)talloc_zero(shadow_mem_ctx,sizeof(SHADOW_COPY_DATA));
+ shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA);
if (shadow_data == NULL) {
DEBUG(0,("talloc_zero() failed!\n"));
+ talloc_destroy(shadow_mem_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
char **ppsetup, uint32 setup_count,
char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count)
+ char **ppdata, uint32 data_count, uint32 max_data_count)
{
NTSTATUS nt_status = NT_STATUS_OK;
- uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
char *params = *ppparams;
char *pdata = *ppdata;
char *entry;
/* access check */
if (current_user.uid != 0) {
- DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
+ DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),conn->user));
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
}
sid_len = IVAL(pdata,4);
+ /* Ensure this is less than 1mb. */
+ if (sid_len > (1024*1024)) {
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
if (data_count < 8+sid_len) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long)(8+sid_len)));
static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
char **ppsetup, uint32 setup_count,
char **ppparams, uint32 parameter_count,
- char **ppdata, uint32 data_count)
+ char **ppdata, uint32 data_count, uint32 max_data_count)
{
char *params = *ppparams;
char *pdata = *ppdata;
ZERO_STRUCT(qt);
/* access check */
- if (conn->admin_user != True) {
+ if (current_user.uid != 0) {
DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),conn->user));
return ERROR_DOS(ERRDOS,ERRnoaccess);
char *inbuf,char *outbuf,int length,int bufsize)
{
int outsize = 0;
+ uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
#if 0 /* Not used. */
uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
- uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
#endif /* Not used. */
uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount);
CVAL(inbuf, smb_wct), 19 + (setup_count/2)));
goto bad_param;
}
-
+
+ /* Don't allow more than 128mb for each value. */
+ if ((total_parameter_count > (1024*1024*128)) || (total_data_count > (1024*1024*128))) {
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
+
/* Allocate the space for the setup, the maximum needed parameters and data */
if(setup_count > 0)
- setup = (char *)malloc(setup_count);
+ setup = (char *)SMB_MALLOC(setup_count);
if (total_parameter_count > 0)
- params = (char *)malloc(total_parameter_count);
+ params = (char *)SMB_MALLOC(total_parameter_count);
if (total_data_count > 0)
- data = (char *)malloc(total_data_count);
+ data = (char *)SMB_MALLOC(total_data_count);
if ((total_parameter_count && !params) || (total_data_count && !data) ||
(setup_count && !setup)) {
}
if (parameter_count) {
- if (parameter_displacement + parameter_count >= total_parameter_count)
+ if (parameter_displacement + parameter_count > total_parameter_count)
goto bad_param;
if ((parameter_displacement + parameter_count < parameter_displacement) ||
(parameter_displacement + parameter_count < parameter_count))
}
if (data_count) {
- if (data_displacement + data_count >= total_data_count)
+ if (data_displacement + data_count > total_data_count)
goto bad_param;
if ((data_displacement + data_count < data_displacement) ||
(data_displacement + data_count < data_count))
length, bufsize,
&setup, setup_count,
¶ms, total_parameter_count,
- &data, total_data_count);
+ &data, total_data_count, max_data_count);
END_PROFILE_NESTED(NT_transact_create);
break;
case NT_TRANSACT_IOCTL:
length, bufsize,
&setup, setup_count,
¶ms, total_parameter_count,
- &data, total_data_count);
+ &data, total_data_count, max_data_count);
END_PROFILE_NESTED(NT_transact_ioctl);
break;
case NT_TRANSACT_SET_SECURITY_DESC:
length, bufsize,
&setup, setup_count,
¶ms, total_parameter_count,
- &data, total_data_count);
+ &data, total_data_count, max_data_count);
END_PROFILE_NESTED(NT_transact_set_security_desc);
break;
case NT_TRANSACT_NOTIFY_CHANGE:
length, bufsize,
&setup, setup_count,
¶ms, total_parameter_count,
- &data, total_data_count);
+ &data, total_data_count, max_data_count);
END_PROFILE_NESTED(NT_transact_notify_change);
break;
case NT_TRANSACT_RENAME:
length, bufsize,
&setup, setup_count,
¶ms, total_parameter_count,
- &data, total_data_count);
+ &data, total_data_count, max_data_count);
END_PROFILE_NESTED(NT_transact_rename);
break;
length, bufsize,
&setup, setup_count,
¶ms, total_parameter_count,
- &data, total_data_count);
+ &data, total_data_count, max_data_count);
END_PROFILE_NESTED(NT_transact_query_security_desc);
break;
#ifdef HAVE_SYS_QUOTAS
length, bufsize,
&setup, setup_count,
¶ms, total_parameter_count,
- &data, total_data_count);
+ &data, total_data_count, max_data_count);
END_PROFILE_NESTED(NT_transact_get_user_quota);
break;
case NT_TRANSACT_SET_USER_QUOTA:
length, bufsize,
&setup, setup_count,
¶ms, total_parameter_count,
- &data, total_data_count);
+ &data, total_data_count, max_data_count);
END_PROFILE_NESTED(NT_transact_set_user_quota);
break;
#endif /* HAVE_SYS_QUOTAS */