[CIFS] Support for setting up SMB sessions to legacy lanman servers part 2
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 7f4013a..4e10e21 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -508,7 +508,7 @@
 		pde->write_proc = multiuser_mount_write;
 
 	pde =
-	    create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
+	    create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs,
 				extended_security_read, NULL);
 	if (pde)
 		pde->write_proc = extended_security_write;
@@ -547,7 +547,7 @@
 	remove_proc_entry("MultiuserMount", proc_fs_cifs);
 	remove_proc_entry("OplockEnabled", proc_fs_cifs);
 /*	remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
-	remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
+	remove_proc_entry("SecurityFlags",proc_fs_cifs);
 /*	remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
 	remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
 	remove_proc_entry("Experimental",proc_fs_cifs);
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 08781a4..e11d8c6 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -26,6 +26,7 @@
 #include "md5.h"
 #include "cifs_unicode.h"
 #include "cifsproto.h"
+#include <linux/ctype.h>
 
 /* Calculate and return the CIFS signature based on the mac key and the smb pdu */
 /* the 16 byte signature must be allocated by the caller  */
@@ -35,6 +36,8 @@
 
 extern void mdfour(unsigned char *out, unsigned char *in, int n);
 extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
+extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
+                       unsigned char *p24);
 	
 static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, 
 				    const char * key, char * signature)
@@ -45,7 +48,7 @@
 		return -EINVAL;
 
 	MD5Init(&context);
-	MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+	MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
 	MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
 	MD5Final(signature,&context);
 	return 0;
@@ -90,7 +93,7 @@
 		return -EINVAL;
 
 	MD5Init(&context);
-	MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+	MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
 	for(i=0;i<n_vec;i++) {
 		if(iov[i].iov_base == NULL) {
 			cERROR(1,("null iovec entry"));
@@ -204,7 +207,7 @@
 
 	E_md4hash(password, temp_key);
 	mdfour(key,temp_key,16);
-	memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
+	memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
 	return 0;
 }
 
@@ -261,6 +264,37 @@
 	kfree(unicode_buf);
 	return 0;
 }
+
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
+{
+	int i;
+	char password_with_pad[CIFS_ENCPWD_SIZE];
+
+	memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
+	strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
+
+	/* calculate old style session key */
+	/* calling toupper is less broken than repeatedly
+	calling nls_toupper would be since that will never
+	work for UTF8, but neither handles multibyte code pages
+	but the only alternative would be converting to UCS-16 (Unicode)
+	(using a routine something like UniStrupr) then
+	uppercasing and then converting back from Unicode - which
+	would only worth doing it if we knew it were utf8. Basically
+	utf8 and other multibyte codepages each need their own strupper
+	function since a byte at a time will ont work. */
+
+	for(i = 0; i < CIFS_ENCPWD_SIZE; i++) {
+		password_with_pad[i] = toupper(password_with_pad[i]);
+	}
+
+	SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key);
+	/* clear password before we return/free memory */
+	memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
+}
+#endif /* CIFS_WEAK_PW_HASH */
+
 void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
 {
 	struct HMACMD5Context context;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7a04204..975e69a 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -158,7 +158,7 @@
 	/* 16th byte of RFC1001 workstation name is always null */
 	char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
 	__u32 sequence_number; /* needed for CIFS PDU signature */
-	char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 
+	char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; 
 };
 
 /*
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index e0ff9b5..1359417 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -116,7 +116,8 @@
 /*
  * Size of the session key (crypto key encrypted with the password
  */
-#define CIFS_SESSION_KEY_SIZE (24)
+#define CIFS_SESS_KEY_SIZE (24)
+#define V2_SESS_KEY_SIZE (86)
 
 /*
  * Maximum user name length
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ff78cf7..59b037f 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -287,6 +287,9 @@
 extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
 extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
 extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
+#endif /* CIFS_WEAK_PW_HASH */
 extern int CIFSSMBCopy(int xid,
 			struct cifsTconInfo *source_tcon,
 			const char *fromName,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index da3154f..6b5be6d 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -438,12 +438,19 @@
 			goto neg_err_exit;
 		} else if((pSMBr->hdr.WordCount == 13) && 
 			(pSMBr->DialectIndex == LANMAN_PROT)) {
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
 			struct lanman_neg_rsp * rsp = 
 				(struct lanman_neg_rsp *)pSMBr;
 
-
-			/* BB Mark ses struct as negotiated lanman level BB */
-			server->secType = LANMAN;
+			if((extended_security & CIFSSEC_MAY_LANMAN) || 
+				(extended_security & CIFSSEC_MAY_PLNTXT))
+				server->secType = LANMAN;
+			else {
+				cERROR(1, ("mount failed weak security disabled"
+					" in /proc/fs/cifs/SecurityFlags"));
+				rc = -EOPNOTSUPP;
+				goto neg_err_exit;
+			}	
 			server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
 			server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
 			server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
@@ -469,6 +476,11 @@
 			}
 
 			cFYI(1,("LANMAN negotiated")); /* BB removeme BB */
+#else /* weak security disabled */
+			cERROR(1,("mount failed, cifs module not built with "
+				"CIFS_WEAK_PW_HASH support"));
+			rc = -EOPNOTSUPP;
+#endif /* WEAK_PW_HASH */
 			goto neg_err_exit;
 		} else if(pSMBr->hdr.WordCount != 17) {
 			/* unknown wct */
@@ -479,8 +491,13 @@
 		server->secMode = pSMBr->SecurityMode;
 		if((server->secMode & SECMODE_USER) == 0)
 			cFYI(1,("share mode security"));
-		server->secType = NTLM; /* BB override default for
-					   NTLMv2 or kerberos v5 */
+		
+		if(extended_security & CIFSSEC_MUST_NTLMV2)
+			server->secType = NTLMv2;
+		else
+			server->secType = NTLM;
+		/* else krb5 ... */
+
 		/* one byte - no need to convert this or EncryptionKeyLen
 		   from little endian */
 		server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 7ffb8f2..e6f3d2f 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1990,7 +1990,7 @@
 
 static int
 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-	      char session_key[CIFS_SESSION_KEY_SIZE],
+	      char session_key[CIFS_SESS_KEY_SIZE],
 	      const struct nls_table *nls_codepage)
 {
 	struct smb_hdr *smb_buffer;
@@ -2048,15 +2048,15 @@
 	pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
 
 	pSMB->req_no_secext.CaseInsensitivePasswordLength = 
-		cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+		cpu_to_le16(CIFS_SESS_KEY_SIZE);
 
 	pSMB->req_no_secext.CaseSensitivePasswordLength =
-	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+	    cpu_to_le16(CIFS_SESS_KEY_SIZE);
 	bcc_ptr = pByteArea(smb_buffer);
-	memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
-	bcc_ptr += CIFS_SESSION_KEY_SIZE;
-	memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
-	bcc_ptr += CIFS_SESSION_KEY_SIZE;
+	memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
+	bcc_ptr += CIFS_SESS_KEY_SIZE;
+	memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
+	bcc_ptr += CIFS_SESS_KEY_SIZE;
 
 	if (ses->capabilities & CAP_UNICODE) {
 		if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
@@ -3004,14 +3004,14 @@
 	SecurityBlob->LmChallengeResponse.Buffer = 0;
 
 	SecurityBlob->NtChallengeResponse.Length =
-	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+	    cpu_to_le16(CIFS_SESS_KEY_SIZE);
 	SecurityBlob->NtChallengeResponse.MaximumLength =
-	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
-	memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
+	    cpu_to_le16(CIFS_SESS_KEY_SIZE);
+	memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
 	SecurityBlob->NtChallengeResponse.Buffer =
 	    cpu_to_le32(SecurityBlobLength);
-	SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
-	bcc_ptr += CIFS_SESSION_KEY_SIZE;
+	SecurityBlobLength += CIFS_SESS_KEY_SIZE;
+	bcc_ptr += CIFS_SESS_KEY_SIZE;
 
 	if (ses->capabilities & CAP_UNICODE) {
 		if (domain == NULL) {
@@ -3350,22 +3350,33 @@
 	bcc_ptr = &pSMB->Password[0];
 	if((ses->server->secMode) & SECMODE_USER) {
 		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
+		*bcc_ptr = 0; /* password is null byte */
 		bcc_ptr++;              /* skip password */
+		/* already aligned so no need to do it below */
 	} else {
-		pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+		pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
 		/* BB FIXME add code to fail this if NTLMv2 or Kerberos
 		   specified as required (when that support is added to
 		   the vfs in the future) as only NTLM or the much
-		   weaker LANMAN (which we do not send) is accepted
+		   weaker LANMAN (which we do not send by default) is accepted
 		   by Samba (not sure whether other servers allow
 		   NTLMv2 password here) */
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+		if((extended_security & CIFSSEC_MAY_LANMAN) && 
+			(ses->server->secType == LANMAN))
+			calc_lanman_hash(ses, bcc_ptr);
+		else
+#endif /* CIFS_WEAK_PW_HASH */
 		SMBNTencrypt(ses->password,
 			     ses->server->cryptKey,
 			     bcc_ptr);
 
-		bcc_ptr += CIFS_SESSION_KEY_SIZE;
-		*bcc_ptr = 0;
-		bcc_ptr++; /* align */
+		bcc_ptr += CIFS_SESS_KEY_SIZE;
+		if(ses->capabilities & CAP_UNICODE) {
+			/* must align unicode strings */
+			*bcc_ptr = 0; /* null byte password */
+			bcc_ptr++;
+		}
 	}
 
 	if(ses->server->secMode & 
@@ -3507,7 +3518,7 @@
 					   struct nls_table * nls_info)
 {
 	int rc = 0;
-	char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
+	char ntlm_session_key[CIFS_SESS_KEY_SIZE];
 	int ntlmv2_flag = FALSE;
 	int first_time = 0;
 
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 5de74d2..a0bcdd6 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -84,7 +84,7 @@
 
 static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
 	{ERRerror, -EIO},
-	{ERRbadpw, -EPERM},
+	{ERRbadpw, -EACCES},  /* was EPERM */
 	{ERRbadtype, -EREMOTE},
 	{ERRaccess, -EACCES},
 	{ERRinvtid, -ENXIO},
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index fdc248f..a52aacb 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -28,12 +28,8 @@
 #include "cifs_debug.h"
 #include "ntlmssp.h"
 #include "nterr.h"
-#include <linux/ctype.h>
 #include <linux/utsname.h>
 
-extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
-                       unsigned char *p24);
-
 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
                          unsigned char *p24);
 
@@ -80,7 +76,7 @@
 	return capabilities;
 }
 
-void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
+static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
 			    const struct nls_table * nls_cp)
 {
 	char * bcc_ptr = *pbcc_area;
@@ -130,7 +126,7 @@
 	*pbcc_area = bcc_ptr;
 }
 
-void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
+static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
 			  const struct nls_table * nls_cp)
 {
 	char * bcc_ptr = *pbcc_area;
@@ -173,7 +169,7 @@
         *pbcc_area = bcc_ptr;
 }
 
-int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
+static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
                             const struct nls_table * nls_cp)
 {
 	int rc = 0;
@@ -255,7 +251,7 @@
 	return rc;
 }
 
-int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
+static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
                             const struct nls_table * nls_cp)
 {
 	int rc = 0;
@@ -317,7 +313,6 @@
 {
 	int rc = 0;
 	int wct;
-	int i;
 	struct smb_hdr *smb_buf;
 	char *bcc_ptr;
 	SESSION_SETUP_ANDX *pSMB;
@@ -343,7 +338,7 @@
 		return -EOPNOTSUPP;
 #endif
 		wct = 10; /* lanman 2 style sessionsetup */
-	} else if(type == NTLM) /* NTLMv2 may retry NTLM */
+	} else if((type == NTLM) || (type == NTLMv2)) /* NTLMv2 may retry NTLM */
 		wct = 13; /* old style NTLM sessionsetup */
 	else /* same size for negotiate or auth, NTLMSSP or extended security */
 		wct = 12;
@@ -360,41 +355,22 @@
 
 	if(type == LANMAN) {
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
-		char lnm_session_key[CIFS_SESSION_KEY_SIZE];
-		char password_with_pad[CIFS_ENCPWD_SIZE];
+		char lnm_session_key[CIFS_SESS_KEY_SIZE];
 
 		/* no capabilities flags in old lanman negotiation */
 
-		pSMB->old_req.PasswordLength = CIFS_SESSION_KEY_SIZE; 
+		pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; 
 		/* BB calculate hash with password */
 		/* and copy into bcc */
 
-		memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
-		strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
-
-		/* calculate old style session key */
-		/* toupper may be less broken then repeatedly calling
-		nls_toupper would be, but neither handles multibyte code pages
-		but the only alternative would be converting to UCS-16 (Unicode)
-		uppercasing and converting back which is only worth doing if
-		we knew it were utf8. utf8 code page needs its own
-		toupper and tolower and strnicmp functions */
-		
-		for(i = 0; i< CIFS_ENCPWD_SIZE; i++) {
-			password_with_pad[i] = toupper(password_with_pad[i]);
-		}
-
-		SMBencrypt(password_with_pad, ses->server->cryptKey,
-			   lnm_session_key);
+		calc_lanman_hash(ses, lnm_session_key);
 
 #ifdef CONFIG_CIFS_DEBUG2
 		cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
-			CIFS_SESSION_KEY_SIZE);
+			CIFS_SESS_KEY_SIZE);
 #endif
-		/* clear password before we return/free memory */
-		memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
-		memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESSION_KEY_SIZE);
-		bcc_ptr += CIFS_SESSION_KEY_SIZE;
+		memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
+		bcc_ptr += CIFS_SESS_KEY_SIZE;
 
 		/* can not sign if LANMAN negotiated so no need
 		to calculate signing key? but what if server
@@ -406,13 +382,13 @@
 		ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
 #endif    
 	} else if (type == NTLM) {
-		char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
+		char ntlm_session_key[CIFS_SESS_KEY_SIZE];
 
 		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
 		pSMB->req_no_secext.CaseInsensitivePasswordLength =
-			cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+			cpu_to_le16(CIFS_SESS_KEY_SIZE);
 		pSMB->req_no_secext.CaseSensitivePasswordLength =
-			cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+			cpu_to_le16(CIFS_SESS_KEY_SIZE);
 	
 		/* calculate session key */
 		SMBNTencrypt(ses->password, ses->server->cryptKey,
@@ -420,15 +396,48 @@
 
 		if(first_time) /* should this be moved into common code 
 				  with similar ntlmv2 path? */
-			cifs_calculate_mac_key(
-				ses->server->mac_signing_key,
+			cifs_calculate_mac_key( ses->server->mac_signing_key,
 				ntlm_session_key, ses->password);
 		/* copy session key */
 
-		memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
-		bcc_ptr += CIFS_SESSION_KEY_SIZE;
-		memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
-		bcc_ptr += CIFS_SESSION_KEY_SIZE;
+		memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
+		bcc_ptr += CIFS_SESS_KEY_SIZE;
+		memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
+		bcc_ptr += CIFS_SESS_KEY_SIZE;
+		if(ses->capabilities & CAP_UNICODE)
+			unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
+		else
+			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+	} else if (type == NTLMv2) {
+		char * v2_sess_key = kmalloc(V2_SESS_KEY_SIZE, GFP_KERNEL);
+
+		if(v2_sess_key == NULL) {
+			cifs_small_buf_release(smb_buf);
+			return -ENOMEM;
+		}
+
+		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+
+		/* LM2 password would be here if we supported it */
+		pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+		/*	cpu_to_le16(LM2_SESS_KEY_SIZE); */
+
+		pSMB->req_no_secext.CaseSensitivePasswordLength =
+			cpu_to_le16(V2_SESS_KEY_SIZE);
+
+		/* calculate session key */
+		CalcNTLMv2_response(ses, v2_sess_key);
+		if(first_time) /* should this be moved into common code
+			          with similar ntlmv2 path? */
+		/*   cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
+				response BB FIXME, v2_sess_key); */
+
+		/* copy session key */
+
+	/*	memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
+		bcc_ptr += LM2_SESS_KEY_SIZE; */
+		memcpy(bcc_ptr, (char *)v2_sess_key, V2_SESS_KEY_SIZE);
+		bcc_ptr += V2_SESS_KEY_SIZE;
 		if(ses->capabilities & CAP_UNICODE)
 			unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
 		else