diff options
author | Volker Lendecke <vlendec@samba.org> | 2007-07-05 16:33:37 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:23:49 -0500 |
commit | fcda5b589633b96415890c569bf23e3e284e0916 (patch) | |
tree | 0bed21f63dd1eaeabff953f157d9f6b556cf335b /source3 | |
parent | 5391750ce6db47678a03db4d67a016acff4fc8e2 (diff) | |
download | samba-fcda5b589633b96415890c569bf23e3e284e0916.tar.gz samba-fcda5b589633b96415890c569bf23e3e284e0916.tar.bz2 samba-fcda5b589633b96415890c569bf23e3e284e0916.zip |
r23726: Explicitly pass down the FLAGS2 field to srvstr_pull_buf. The next
checkin will pull this up to srvstr_get_path. At that point we can get more
independent of the inbuf, the base_ptr in pull_string will only be used
to satisfy UCS2 alignment constraints.
(This used to be commit 836782b07bf133e9b2598c4a089f1c810e4c7754)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/safe_string.h | 6 | ||||
-rw-r--r-- | source3/include/srvstr.h | 8 | ||||
-rw-r--r-- | source3/lib/charcnv.c | 12 | ||||
-rw-r--r-- | source3/libsmb/clistr.c | 4 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp_parse.c | 21 | ||||
-rw-r--r-- | source3/libsmb/smbencrypt.c | 3 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 4 | ||||
-rw-r--r-- | source3/smbd/message.c | 12 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 3 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 3 | ||||
-rw-r--r-- | source3/smbd/reply.c | 27 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 43 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 6 |
13 files changed, 99 insertions, 53 deletions
diff --git a/source3/include/safe_string.h b/source3/include/safe_string.h index d278e29aca..3a732e11e1 100644 --- a/source3/include/safe_string.h +++ b/source3/include/safe_string.h @@ -164,7 +164,7 @@ size_t __unsafe_string_function_usage_here_char__(void); #define safe_strcpy(dest,src,maxlength) safe_strcpy_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE,dest,src,maxlength) #define safe_strcat(dest,src,maxlength) safe_strcat_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE,dest,src,maxlength) #define push_string(base_ptr, dest, src, dest_len, flags) push_string_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, base_ptr, dest, src, dest_len, flags) -#define pull_string(base_ptr, dest, src, dest_len, src_len, flags) pull_string_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, base_ptr, dest, src, dest_len, src_len, flags) +#define pull_string(base_ptr, smb_flags2, dest, src, dest_len, src_len, flags) pull_string_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, base_ptr, smb_flags2, dest, src, dest_len, src_len, flags) #define clistr_push(cli, dest, src, dest_len, flags) clistr_push_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, cli, dest, src, dest_len, flags) #define clistr_pull(cli, dest, src, dest_len, src_len, flags) clistr_pull_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, cli, dest, src, dest_len, src_len, flags) #define srvstr_push(base_ptr, dest, src, dest_len, flags) srvstr_push_fn2(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, base_ptr, dest, src, dest_len, flags) @@ -193,10 +193,10 @@ size_t __unsafe_string_function_usage_here_char__(void); ? __unsafe_string_function_usage_here_size_t__() \ : push_string_fn(fn_name, fn_line, base_ptr, dest, src, dest_len, flags)) -#define pull_string_fn2(fn_name, fn_line, base_ptr, dest, src, dest_len, src_len, flags) \ +#define pull_string_fn2(fn_name, fn_line, base_ptr, smb_flags2, dest, src, dest_len, src_len, flags) \ (CHECK_STRING_SIZE(dest, dest_len) \ ? __unsafe_string_function_usage_here_size_t__() \ - : pull_string_fn(fn_name, fn_line, base_ptr, dest, src, dest_len, src_len, flags)) + : pull_string_fn(fn_name, fn_line, base_ptr, smb_flags2, dest, src, dest_len, src_len, flags)) #define clistr_push_fn2(fn_name, fn_line, cli, dest, src, dest_len, flags) \ (CHECK_STRING_SIZE(dest, dest_len) \ diff --git a/source3/include/srvstr.h b/source3/include/srvstr.h index 1029df53ae..99a7407a6a 100644 --- a/source3/include/srvstr.h +++ b/source3/include/srvstr.h @@ -18,14 +18,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define srvstr_pull(base_ptr, dest, src, dest_len, src_len, flags) \ - pull_string(base_ptr, dest, src, dest_len, src_len, flags) +#define srvstr_pull(base_ptr, smb_flags2, dest, src, dest_len, src_len, flags) \ + pull_string(base_ptr, smb_flags2, dest, src, dest_len, src_len, flags) /* pull a string from the smb_buf part of a packet. In this case the string can either be null terminated or it can be terminated by the end of the smbbuf area */ -#define srvstr_pull_buf(inbuf, dest, src, dest_len, flags) \ - pull_string(inbuf, dest, src, dest_len, smb_bufrem(inbuf, src), flags) +#define srvstr_pull_buf(inbuf, smb_flags2, dest, src, dest_len, flags) \ + pull_string(inbuf, smb_flags2, dest, src, dest_len, smb_bufrem(inbuf, src), flags) diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 35343b2f0a..5ca7f201c2 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -1376,16 +1376,24 @@ size_t push_string_fn(const char *function, unsigned int line, const void *base_ The resulting string in "dest" is always null terminated. **/ -size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +size_t pull_string_fn(const char *function, unsigned int line, + const void *base_ptr, uint16 smb_flags2, char *dest, + const void *src, size_t dest_len, size_t src_len, + int flags) { #ifdef DEVELOPER if (dest_len != (size_t)-1) clobber_region(function, line, dest, dest_len); #endif + if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) { + smb_panic("No base ptr to get flg2 and neither ASCII nor " + "UNICODE defined"); + } + if (!(flags & STR_ASCII) && \ ((flags & STR_UNICODE || \ - (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) { + (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) { return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags); } return pull_ascii(dest, src, dest_len, src_len, flags); diff --git a/source3/libsmb/clistr.c b/source3/libsmb/clistr.c index 6191f99ea9..4d18434ff9 100644 --- a/source3/libsmb/clistr.c +++ b/source3/libsmb/clistr.c @@ -43,7 +43,9 @@ size_t clistr_pull_fn(const char *function, unsigned int line, int dest_len, int src_len, int flags) { - return pull_string_fn(function, line, cli->inbuf, dest, src, dest_len, src_len, flags); + return pull_string_fn(function, line, cli->inbuf, + SVAL(cli->inbuf, smb_flg2), dest, src, dest_len, + src_len, flags); } diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c index 3d96fa5f1a..a3977dbc01 100644 --- a/source3/libsmb/ntlmssp_parse.c +++ b/source3/libsmb/ntlmssp_parse.c @@ -220,9 +220,10 @@ BOOL msrpc_parse(const DATA_BLOB *blob, return False; if (0 < len1) { - pull_string(NULL, p, blob->data + ptr, sizeof(p), - len1, - STR_UNICODE|STR_NOALIGN); + pull_string( + NULL, 0, p, + blob->data + ptr, sizeof(p), + len1, STR_UNICODE|STR_NOALIGN); (*ps) = smb_xstrdup(p); } else { (*ps) = smb_xstrdup(""); @@ -248,9 +249,10 @@ BOOL msrpc_parse(const DATA_BLOB *blob, return False; if (0 < len1) { - pull_string(NULL, p, blob->data + ptr, sizeof(p), - len1, - STR_ASCII|STR_NOALIGN); + pull_string( + NULL, 0, p, + blob->data + ptr, sizeof(p), + len1, STR_ASCII|STR_NOALIGN); (*ps) = smb_xstrdup(p); } else { (*ps) = smb_xstrdup(""); @@ -300,9 +302,10 @@ BOOL msrpc_parse(const DATA_BLOB *blob, if (blob->data + head_ofs < (uint8 *)head_ofs || blob->data + head_ofs < blob->data) return False; - head_ofs += pull_string(NULL, p, blob->data+head_ofs, sizeof(p), - blob->length - head_ofs, - STR_ASCII|STR_TERMINATE); + head_ofs += pull_string( + NULL, 0, p, blob->data+head_ofs, sizeof(p), + blob->length - head_ofs, + STR_ASCII|STR_TERMINATE); if (strcmp(s, p) != 0) { return False; } diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 2586128966..4e8c5066a8 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -555,7 +555,8 @@ BOOL decode_pw_buffer(uint8 in_buffer[516], char *new_pwrd, } /* decode into the return buffer. Buffer length supplied */ - *new_pw_len = pull_string(NULL, new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size, + *new_pw_len = pull_string(NULL, 0, new_pwrd, + &in_buffer[512 - byte_len], new_pwrd_size, byte_len, string_flags); #ifdef DEBUG_PASSWORD diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 6b647fc72b..ce26b53e1b 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -543,8 +543,8 @@ int reply_trans(connection_struct *conn, state->one_way = BITSETW(inbuf+smb_vwv5,1); memset(state->name, '\0',sizeof(state->name)); - srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf), - sizeof(state->name), STR_TERMINATE); + srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), state->name, + smb_buf(inbuf), sizeof(state->name), STR_TERMINATE); if ((dscnt > state->total_data) || (pscnt > state->total_param)) goto bad_param; diff --git a/source3/smbd/message.c b/source3/smbd/message.c index e6a5015276..f390e539b0 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -134,8 +134,10 @@ int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, outsize = set_message(inbuf,outbuf,0,0,True); p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgfrom, p, + sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgto, p, + sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; msg = p; @@ -176,8 +178,10 @@ int reply_sendstrt(connection_struct *conn, char *inbuf,char *outbuf, int dum_si msgpos = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgfrom, p, + sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgto, p, + sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1; DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) ); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 7e17e3b938..782c90cba1 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -382,7 +382,8 @@ static int do_ntcreate_pipe_open(connection_struct *conn, char *p = NULL; uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); - srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE); + srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), fname, smb_buf(inbuf), + sizeof(fname), STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) { return ret; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index aba2fe69c5..1da2f0c22f 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -65,7 +65,8 @@ int reply_open_pipe_and_X(connection_struct *conn, int i; /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull_buf(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE); + srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), pipe_name, + smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 76265ed464..ac06f2fd6d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -218,9 +218,11 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de #endif if (src_len == 0) { - ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags); + ret = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dest, src, + dest_len, flags); } else { - ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags); + ret = srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), dest, src, + dest_len, src_len, flags); } *contains_wcard = False; @@ -255,9 +257,11 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len #endif if (src_len == 0) { - ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags); + ret = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dest, src, + dest_len, flags); } else { - ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags); + ret = srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), dest, src, + dest_len, src_len, flags); } if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) { @@ -391,10 +395,13 @@ int reply_tcon(connection_struct *conn, *service_buf = *password = *dev = 0; p = smb_buf(inbuf)+1; - p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1; - pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), service_buf, p, + sizeof(service_buf), STR_TERMINATE) + 1; + pwlen = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), password, p, + sizeof(password), STR_TERMINATE) + 1; p += pwlen; - p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1; + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dev, p, sizeof(dev), + STR_TERMINATE) + 1; p = strrchr_m(service_buf,'\\'); if (p) { @@ -478,7 +485,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt p = smb_buf(inbuf) + passlen + 1; } - p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), path, p, + sizeof(path), STR_TERMINATE); /* * the service name can be either: \\server\share @@ -495,7 +503,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt else fstrcpy(service,path); - p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII); + p += srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), client_devicetype, p, + sizeof(client_devicetype), 6, STR_ASCII); DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service)); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 22c598a654..3ed338bda7 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1057,9 +1057,12 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, #endif p2 = inbuf + smb_vwv13 + data_blob_len; - p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE); - p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE); - p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE); + p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_os, p2, + sizeof(native_os), STR_TERMINATE); + p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_lanman, p2, + sizeof(native_lanman), STR_TERMINATE); + p2 += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), primary_domain, p2, + sizeof(primary_domain), STR_TERMINATE); DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", native_os, native_lanman, primary_domain)); @@ -1283,7 +1286,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, plaintext_password.data[passlen1] = 0; } - srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE); + srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), user, + smb_buf(inbuf)+passlen1, sizeof(user), + STR_TERMINATE); *domain = 0; } else { @@ -1363,21 +1368,28 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, if (unic && (passlen2 == 0) && passlen1) { /* Only a ascii plaintext password was sent. */ - srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass), - passlen1, STR_TERMINATE|STR_ASCII); + srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pass, + smb_buf(inbuf), sizeof(pass), + passlen1, STR_TERMINATE|STR_ASCII); } else { - srvstr_pull(inbuf, pass, smb_buf(inbuf), - sizeof(pass), unic ? passlen2 : passlen1, - STR_TERMINATE); + srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pass, + smb_buf(inbuf), sizeof(pass), + unic ? passlen2 : passlen1, + STR_TERMINATE); } plaintext_password = data_blob(pass, strlen(pass)+1); } p += passlen1 + passlen2; - p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE); - p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), user, p, + sizeof(user), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), domain, p, + sizeof(domain), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), native_os, + p, sizeof(native_os), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), + native_lanman, p, sizeof(native_lanman), + STR_TERMINATE); /* not documented or decoded by Ethereal but there is one more string in the extra bytes which is the same as the PrimaryDomain when using @@ -1387,7 +1399,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, byte_count = SVAL(inbuf, smb_vwv13); if ( PTR_DIFF(p, save_p) < byte_count) - p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE); + p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), + primary_domain, p, + sizeof(primary_domain), + STR_TERMINATE); else fstrcpy( primary_domain, "null" ); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8d4f505e09..2219ebd1c1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4530,7 +4530,8 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, return NT_STATUS_ACCESS_DENIED; } - srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE); + srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata, + sizeof(link_target), total_data, STR_TERMINATE); /* !widelinks forces the target path to be within the share. */ /* This means we can interpret the target as a pathname. */ @@ -6366,7 +6367,8 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* if(!lp_host_msdfs()) return ERROR_DOS(ERRDOS,ERRbadfunc); - srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), total_params - 2, STR_TERMINATE); + srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2], + sizeof(pathname), total_params - 2, STR_TERMINATE); if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0) return ERROR_NT(status); |