1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsCommandLine.h"
7 #include "mozilla/CmdLineAndEnvUtils.h"
8 #include "WinRemoteMessage.h"
10 using namespace mozilla
;
12 #define MOZ_MAGIC_COPYDATA_PREFIX "🔥🦊"
14 WinRemoteMessageSender::WinRemoteMessageSender(int32_t aArgc
,
16 const nsAString
& aWorkingDir
)
17 : mData({static_cast<DWORD
>(
18 WinRemoteMessageVersion::NullSeparatedArguments
)}) {
19 mCmdLineBuffer
.AppendLiteral(MOZ_MAGIC_COPYDATA_PREFIX
"\0");
20 AppendUTF16toUTF8(aWorkingDir
, mCmdLineBuffer
);
21 mCmdLineBuffer
.Append('\0');
23 for (int32_t i
= 0; i
< aArgc
; i
++) {
24 mCmdLineBuffer
.Append(aArgv
[i
]);
25 mCmdLineBuffer
.Append('\0');
29 mData
.cbData
= mCmdLineBuffer
.GetMutableData(&mutableBuffer
);
30 mData
.lpData
= mutableBuffer
;
33 COPYDATASTRUCT
* WinRemoteMessageSender::CopyData() { return &mData
; }
35 nsresult
WinRemoteMessageReceiver::ParseV2(const nsAString
& aBuffer
) {
36 CommandLineParserWin
<char16_t
> parser
;
37 size_t cch
= parser
.HandleCommandLine(aBuffer
);
38 ++cch
; // skip a null char
40 nsCOMPtr
<nsIFile
> workingDir
;
41 if (cch
< aBuffer
.Length()) {
42 NS_NewLocalFile(Substring(aBuffer
, cch
), false, getter_AddRefs(workingDir
));
45 int argc
= parser
.Argc();
46 Vector
<nsAutoCString
> utf8args
;
47 if (!utf8args
.reserve(argc
)) {
48 return NS_ERROR_OUT_OF_MEMORY
;
51 UniquePtr
<const char*[]> argv(new const char*[argc
]);
52 for (int i
= 0; i
< argc
; ++i
) {
53 utf8args
.infallibleAppend(NS_ConvertUTF16toUTF8(parser
.Argv()[i
]));
54 argv
[i
] = utf8args
[i
].get();
57 mCommandLine
= new nsCommandLine();
58 return mCommandLine
->Init(argc
, argv
.get(), workingDir
,
59 nsICommandLine::STATE_REMOTE_AUTO
);
62 nsresult
WinRemoteMessageReceiver::ParseV3(const nsACString
& aBuffer
) {
63 nsCOMPtr
<nsIFile
> workingDir
;
65 // String should start with the magic sequence followed by null
66 int32_t nextNul
= aBuffer
.FindChar('\0');
68 return NS_ERROR_FAILURE
;
71 if (!Substring(aBuffer
, 0, nextNul
).Equals(MOZ_MAGIC_COPYDATA_PREFIX
)) {
72 return NS_ERROR_FAILURE
;
75 int32_t pos
= nextNul
+ 1;
76 nextNul
= aBuffer
.FindChar('\0', pos
);
78 return NS_ERROR_FAILURE
;
81 nsresult rv
= NS_NewLocalFile(
82 NS_ConvertUTF8toUTF16(Substring(aBuffer
, pos
, nextNul
- pos
)), false,
83 getter_AddRefs(workingDir
));
84 NS_ENSURE_SUCCESS(rv
, rv
);
87 nsTArray
<const char*> argv
;
90 nextNul
= aBuffer
.FindChar('\0', pos
);
95 // Because each argument is null terminated we can just add the pointer to
96 // the array directly.
97 argv
.AppendElement(aBuffer
.BeginReading() + pos
);
101 // There should always be at least one argument, the path to the binary.
102 if (argv
.IsEmpty()) {
103 return NS_ERROR_FAILURE
;
106 mCommandLine
= new nsCommandLine();
107 return mCommandLine
->Init(argv
.Length(), argv
.Elements(), workingDir
,
108 nsICommandLine::STATE_REMOTE_AUTO
);
111 nsresult
WinRemoteMessageReceiver::Parse(const COPYDATASTRUCT
* aMessageData
) {
112 switch (static_cast<WinRemoteMessageVersion
>(aMessageData
->dwData
)) {
113 case WinRemoteMessageVersion::CommandLineAndWorkingDirInUtf16
:
115 nsDependentSubstring(reinterpret_cast<wchar_t*>(aMessageData
->lpData
),
116 aMessageData
->cbData
/ sizeof(char16_t
)));
117 case WinRemoteMessageVersion::NullSeparatedArguments
:
118 return ParseV3(nsDependentCSubstring(
119 reinterpret_cast<char*>(aMessageData
->lpData
), aMessageData
->cbData
));
121 MOZ_ASSERT_UNREACHABLE("Unsupported message version");
122 return NS_ERROR_FAILURE
;
126 nsICommandLineRunner
* WinRemoteMessageReceiver::CommandLineRunner() {
130 #undef MOZ_MAGIC_COPYDATA_PREFIX