From 112cac7e8477bcb6f0432a0575c67d70d250eaa1 Mon Sep 17 00:00:00 2001
From: midipix <writeonce@midipix.org>
Date: Fri, 22 Dec 2017 09:56:11 +0000
Subject: tt_array_copy_utf16(): properly implement the interp-optarg-script
 semantics.

---
 include/ntapi/nt_argv.h         |  4 +--
 src/argv/ntapi_tt_array_utf16.c | 77 +++++++++++++++++++++++++++++------------
 2 files changed, 56 insertions(+), 25 deletions(-)

diff --git a/include/ntapi/nt_argv.h b/include/ntapi/nt_argv.h
index a75d538..317fb21 100644
--- a/include/ntapi/nt_argv.h
+++ b/include/ntapi/nt_argv.h
@@ -170,9 +170,9 @@ typedef int32_t __stdcall	ntapi_tt_array_copy_utf16(
 	__out	int *			argc,
 	__in	const wchar16_t **	wargv,
 	__in	const wchar16_t **	wenvp,
-	__in	const wchar16_t *	image_name	__optional,
-	__in	const wchar16_t *	interpreter	__optional,
+	__in	const wchar16_t *	interp		__optional,
 	__in	const wchar16_t *	optarg		__optional,
+	__in	const wchar16_t *	script		__optional,
 	__in	void *			base,
 	__out	void *			buffer,
 	__in	size_t			buflen,
diff --git a/src/argv/ntapi_tt_array_utf16.c b/src/argv/ntapi_tt_array_utf16.c
index 266fd8e..fa0892d 100644
--- a/src/argv/ntapi_tt_array_utf16.c
+++ b/src/argv/ntapi_tt_array_utf16.c
@@ -21,9 +21,9 @@ int32_t __stdcall __ntapi_tt_array_copy_utf16(
 	__out	int *			argc,
 	__in	const wchar16_t **	wargv,
 	__in	const wchar16_t **	wenvp,
-	__in	const wchar16_t *	image_name	__optional,
-	__in	const wchar16_t *	interpreter	__optional,
-	__in	const wchar16_t *	optarg		__optional,
+	__in	const wchar16_t *	interp,
+	__in	const wchar16_t *	optarg,
+	__in	const wchar16_t *	script,
 	__in	void *			base,
 	__out	void *			buffer,
 	__in	size_t			buflen,
@@ -31,40 +31,55 @@ int32_t __stdcall __ntapi_tt_array_copy_utf16(
 {
 	const wchar16_t **	parg;
 	const wchar16_t *	warg;
-	const wchar16_t *	dummy;
+	const wchar16_t *	mark;
 	wchar16_t *		wch;
 	ptrdiff_t		diff;
 	ptrdiff_t		ptrs;
 	size_t			needed;
-
-	/* unused params */
-	(void)interpreter;
-	(void)optarg;
+	const wchar16_t *	dummy[2] = {0,0};
 
 	/* fallback */
-	dummy = 0;
-	wargv = wargv ? wargv : &dummy;
-	wenvp = wenvp ? wenvp : &dummy;
+	wargv = wargv ? wargv : dummy;
+	wenvp = wenvp ? wenvp : dummy;
 
 	/* ptrs, needed */
 	ptrs   = 0;
 	needed = 0;
 
-	if (image_name) {
+	/* interp */
+	if (interp) {
+		ptrs++;
+		needed += sizeof(wchar16_t *)
+			+ __ntapi->tt_string_null_offset_short((const int16_t *)interp)
+			+ sizeof(wchar16_t);
+	}
+
+	/* optarg */
+	if (interp) {
+		ptrs++;
+		needed += sizeof(wchar16_t *)
+			+ __ntapi->tt_string_null_offset_short((const int16_t *)optarg)
+			+ sizeof(wchar16_t);
+	}
+
+	/* script / wargv[0] */
+	 if ((mark = script ? script : wargv[0])) {
 		ptrs++;
 		needed += sizeof(wchar16_t *)
-			+ __ntapi->tt_string_null_offset_short((const int16_t *)image_name)
+			+ __ntapi->tt_string_null_offset_short((const int16_t *)mark)
 			+ sizeof(wchar16_t);
 	}
 
-	for (parg=wargv; *parg; parg++)
+	/* wargv */
+	for (parg=&wargv[1]; *parg; parg++)
 		needed += sizeof(wchar16_t *)
 			+ __ntapi->tt_string_null_offset_short((const int16_t *)*parg)
 			+ sizeof(wchar16_t);
 
-	ptrs += (parg - wargv);
+	ptrs += (parg - &wargv[1]);
 	*argc = (int)ptrs;
 
+	/* wenvp */
 	for (parg=wenvp; *parg; parg++)
 		needed += sizeof(wchar16_t *)
 			+ __ntapi->tt_string_null_offset_short((const int16_t *)*parg)
@@ -72,8 +87,8 @@ int32_t __stdcall __ntapi_tt_array_copy_utf16(
 
 	ptrs += (parg - wenvp);
 
-	ptrs    += 2;
-	needed  += 2*sizeof(wchar16_t *);
+	ptrs   += 2;
+	needed += 2*sizeof(wchar16_t *);
 	blklen  = blklen ? blklen : &needed;
 	*blklen = needed;
 
@@ -85,16 +100,32 @@ int32_t __stdcall __ntapi_tt_array_copy_utf16(
 	wch  = (wchar16_t *)(parg+ptrs);
 	diff = (uintptr_t)base / sizeof(wchar16_t);
 
-	/* image_name */
-	if (image_name) {
+	/* interp */
+	if (interp) {
+		*parg++ = wch-diff;
+		for (warg=interp; *warg; warg++,wch++)
+			*wch = *warg;
+		*wch++ = '\0';
+	}
+
+	/* optarg */
+	if (optarg) {
+		*parg++ = wch-diff;
+		for (warg=optarg; *warg; warg++,wch++)
+			*wch = *warg;
+		*wch++ = '\0';
+	}
+
+	/* script / wargv[0] */
+	if ((mark = script ? script : wargv[0])) {
 		*parg++ = wch-diff;
-		for (warg=image_name; *warg; warg++,wch++)
+		for (warg=mark; *warg; warg++,wch++)
 			*wch = *warg;
 		*wch++ = '\0';
 	}
 
-	/* argv */
-	for (; *wargv; wargv++) {
+	/* wargv */
+	for (++wargv; *wargv; wargv++) {
 		*parg++=wch-diff;
 		for (warg=*wargv; *warg; warg++,wch++)
 			*wch = *warg;
@@ -103,7 +134,7 @@ int32_t __stdcall __ntapi_tt_array_copy_utf16(
 
 	*parg++ = 0;
 
-	/* envp */
+	/* wenvp */
 	for (; *wenvp; wenvp++) {
 		*parg++=wch-diff;
 		for (warg=*wenvp; *warg; warg++,wch++)
-- 
cgit v1.2.3