forked from mirrors/gecko-dev
		
	 cc15f3d517
			
		
	
	
		cc15f3d517
		
	
	
	
	
		
			
			Moves GetWindowInfo, GetKeyState, SetCursorPos, GetSaveFileNameW and GetOpenFileNameW to the new FunctionHook and FunctionBroker systems.
		
			
				
	
	
		
			359 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			359 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
 | |
| /* vim: set sw=2 ts=8 et tw=80 : */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include "FunctionBrokerIPCUtils.h"
 | |
| 
 | |
| #if defined(XP_WIN)
 | |
| 
 | |
| #include <schannel.h>
 | |
| 
 | |
| /* these defines are missing from mingw headers */
 | |
| #ifndef SP_PROT_TLS1_1_CLIENT
 | |
| #define SP_PROT_TLS1_1_CLIENT 0x00000200
 | |
| #endif
 | |
| 
 | |
| #ifndef SP_PROT_TLS1_2_CLIENT
 | |
| #define SP_PROT_TLS1_2_CLIENT 0x00000800
 | |
| #endif
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace plugins {
 | |
| 
 | |
| mozilla::LazyLogModule sPluginHooksLog("PluginHooks");
 | |
| 
 | |
| static const DWORD SCHANNEL_SUPPORTED_PROTOCOLS =
 | |
|   SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
 | |
| 
 | |
| static const DWORD SCHANNEL_SUPPORTED_FLAGS =
 | |
|   SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS |
 | |
|   SCH_CRED_REVOCATION_CHECK_END_CERT;
 | |
| 
 | |
| void
 | |
| OpenFileNameIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
 | |
| {
 | |
|   mHwndOwner = nullptr;
 | |
| 
 | |
|   // Filter is double-NULL terminated.  mFilter should include the double-NULL.
 | |
|   mHasFilter = aLpofn->lpstrFilter != nullptr;
 | |
|   if (mHasFilter) {
 | |
|     uint32_t dNullIdx = 0;
 | |
|     while (aLpofn->lpstrFilter[dNullIdx] != L'\0' ||
 | |
|            aLpofn->lpstrFilter[dNullIdx+1] != L'\0') {
 | |
|       dNullIdx++;
 | |
|     }
 | |
|     mFilter.assign(aLpofn->lpstrFilter, dNullIdx+2);
 | |
|   }
 | |
|   mHasCustomFilter = aLpofn->lpstrCustomFilter != nullptr;
 | |
|   if (mHasCustomFilter) {
 | |
|     mCustomFilterIn = std::wstring(aLpofn->lpstrCustomFilter);
 | |
|     mNMaxCustFilterOut =
 | |
|       aLpofn->nMaxCustFilter - (wcslen(aLpofn->lpstrCustomFilter) + 1);
 | |
|   }
 | |
|   else {
 | |
|     mNMaxCustFilterOut = 0;
 | |
|   }
 | |
|   mFilterIndex = aLpofn->nFilterIndex;
 | |
|   mFile = std::wstring(aLpofn->lpstrFile);
 | |
|   mNMaxFile = aLpofn->nMaxFile;
 | |
|   mNMaxFileTitle =
 | |
|     aLpofn->lpstrFileTitle != nullptr ? aLpofn->nMaxFileTitle : 0;
 | |
|   mHasInitialDir = aLpofn->lpstrInitialDir != nullptr;
 | |
|   if (mHasInitialDir) {
 | |
|     mInitialDir = std::wstring(aLpofn->lpstrInitialDir);
 | |
|   }
 | |
|   mHasTitle = aLpofn->lpstrTitle != nullptr;
 | |
|   if (mHasTitle) {
 | |
|     mTitle = std::wstring(aLpofn->lpstrTitle);
 | |
|   }
 | |
|   mHasDefExt = aLpofn->lpstrDefExt != nullptr;
 | |
|   if (mHasDefExt) {
 | |
|     mDefExt = std::wstring(aLpofn->lpstrDefExt);
 | |
|   }
 | |
| 
 | |
|   mFlags = aLpofn->Flags;
 | |
|   // If the user sets OFN_ALLOWMULTISELECT then we require OFN_EXPLORER
 | |
|   // as well.  Without OFN_EXPLORER, the method has ancient legacy
 | |
|   // behavior that we don't support.
 | |
|   MOZ_ASSERT((mFlags & OFN_EXPLORER) || !(mFlags & OFN_ALLOWMULTISELECT));
 | |
| 
 | |
|   // We ignore any visual customization and callbacks that the user set.
 | |
|   mFlags &= ~(OFN_ENABLEHOOK | OFN_ENABLETEMPLATEHANDLE | OFN_ENABLETEMPLATE);
 | |
| 
 | |
|   mFlagsEx = aLpofn->FlagsEx;
 | |
| }
 | |
| 
 | |
| void
 | |
| OpenFileNameIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
 | |
| {
 | |
|   aLpofn->lStructSize = sizeof(OPENFILENAMEW);
 | |
|   aLpofn->hwndOwner = mHwndOwner;
 | |
|   if (mHasFilter) {
 | |
|     memcpy(const_cast<LPWSTR>(aLpofn->lpstrFilter),
 | |
|            mFilter.data(), mFilter.size() * sizeof(wchar_t));
 | |
|   }
 | |
|   if (mHasCustomFilter) {
 | |
|     aLpofn->nMaxCustFilter = mCustomFilterIn.size() + 1 + mNMaxCustFilterOut;
 | |
|     wcscpy(aLpofn->lpstrCustomFilter, mCustomFilterIn.c_str());
 | |
|     memset(aLpofn->lpstrCustomFilter + mCustomFilterIn.size() + 1, 0,
 | |
|            mNMaxCustFilterOut * sizeof(wchar_t));
 | |
|   }
 | |
|   else {
 | |
|     aLpofn->nMaxCustFilter = 0;
 | |
|   }
 | |
|   aLpofn->nFilterIndex = mFilterIndex;
 | |
|   if (mNMaxFile > 0) {
 | |
|     wcsncpy(aLpofn->lpstrFile, mFile.c_str(),
 | |
|             std::min(static_cast<uint32_t>(mFile.size()+1), mNMaxFile));
 | |
|     aLpofn->lpstrFile[mNMaxFile - 1] = L'\0';
 | |
|   }
 | |
|   aLpofn->nMaxFile = mNMaxFile;
 | |
|   aLpofn->nMaxFileTitle = mNMaxFileTitle;
 | |
|   if (mHasInitialDir) {
 | |
|     wcscpy(const_cast<LPWSTR>(aLpofn->lpstrInitialDir), mInitialDir.c_str());
 | |
|   }
 | |
|   if (mHasTitle) {
 | |
|     wcscpy(const_cast<LPWSTR>(aLpofn->lpstrTitle), mTitle.c_str());
 | |
|   }
 | |
|   aLpofn->Flags = mFlags;  /* TODO: Consider adding OFN_NOCHANGEDIR */
 | |
|   if (mHasDefExt) {
 | |
|     wcscpy(const_cast<LPWSTR>(aLpofn->lpstrDefExt), mDefExt.c_str());
 | |
|   }
 | |
|   aLpofn->FlagsEx = mFlagsEx;
 | |
| }
 | |
| 
 | |
| void
 | |
| OpenFileNameIPC::AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const
 | |
| {
 | |
|   if (mHasFilter) {
 | |
|     // mFilter is double-NULL terminated and it includes the double-NULL in its length.
 | |
|     aLpofn->lpstrFilter =
 | |
|       static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mFilter.size())));
 | |
|   }
 | |
|   if (mHasCustomFilter) {
 | |
|     aLpofn->lpstrCustomFilter =
 | |
|       static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * (mCustomFilterIn.size() + 1 + mNMaxCustFilterOut)));
 | |
|   }
 | |
|   aLpofn->lpstrFile =
 | |
|     static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFile));
 | |
|   if (mNMaxFileTitle > 0) {
 | |
|     aLpofn->lpstrFileTitle =
 | |
|       static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFileTitle));
 | |
|   }
 | |
|   if (mHasInitialDir) {
 | |
|     aLpofn->lpstrInitialDir =
 | |
|       static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mInitialDir.size() + 1)));
 | |
|   }
 | |
|   if (mHasTitle) {
 | |
|     aLpofn->lpstrTitle =
 | |
|       static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mTitle.size() + 1)));
 | |
|   }
 | |
|   if (mHasDefExt) {
 | |
|     aLpofn->lpstrDefExt =
 | |
|       static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mDefExt.size() + 1)));
 | |
|   }
 | |
| }
 | |
| 
 | |
| // static
 | |
| void
 | |
| OpenFileNameIPC::FreeOfnStrings(LPOPENFILENAMEW aLpofn)
 | |
| {
 | |
|   if (aLpofn->lpstrFilter) {
 | |
|     free(const_cast<LPWSTR>(aLpofn->lpstrFilter));
 | |
|   }
 | |
|   if (aLpofn->lpstrCustomFilter) {
 | |
|     free(aLpofn->lpstrCustomFilter);
 | |
|   }
 | |
|   if (aLpofn->lpstrFile) {
 | |
|     free(aLpofn->lpstrFile);
 | |
|   }
 | |
|   if (aLpofn->lpstrFileTitle) {
 | |
|     free(aLpofn->lpstrFileTitle);
 | |
|   }
 | |
|   if (aLpofn->lpstrInitialDir) {
 | |
|     free(const_cast<LPWSTR>(aLpofn->lpstrInitialDir));
 | |
|   }
 | |
|   if (aLpofn->lpstrTitle) {
 | |
|     free(const_cast<LPWSTR>(aLpofn->lpstrTitle));
 | |
|   }
 | |
|   if (aLpofn->lpstrDefExt) {
 | |
|     free(const_cast<LPWSTR>(aLpofn->lpstrDefExt));
 | |
|   }
 | |
| }
 | |
| 
 | |
| void
 | |
| OpenFileNameRetIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
 | |
| {
 | |
|   if (aLpofn->lpstrCustomFilter != nullptr) {
 | |
|     mCustomFilterOut =
 | |
|       std::wstring(aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1);
 | |
|   }
 | |
|   mFile.assign(aLpofn->lpstrFile, aLpofn->nMaxFile);
 | |
|   if (aLpofn->lpstrFileTitle != nullptr) {
 | |
|     mFileTitle.assign(aLpofn->lpstrFileTitle, wcslen(aLpofn->lpstrFileTitle) + 1);
 | |
|   }
 | |
|   mFileOffset = aLpofn->nFileOffset;
 | |
|   mFileExtension = aLpofn->nFileExtension;
 | |
| }
 | |
| 
 | |
| void
 | |
| OpenFileNameRetIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
 | |
| {
 | |
|   if (aLpofn->lpstrCustomFilter) {
 | |
|     LPWSTR secondString =
 | |
|       aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1;
 | |
|     const wchar_t* customFilterOut = mCustomFilterOut.c_str();
 | |
|     MOZ_ASSERT(wcslen(aLpofn->lpstrCustomFilter) + 1 +
 | |
|                wcslen(customFilterOut) + 1 + 1 <= aLpofn->nMaxCustFilter);
 | |
|     wcscpy(secondString, customFilterOut);
 | |
|     secondString[wcslen(customFilterOut) + 1] = L'\0';  // terminated with two NULLs
 | |
|   }
 | |
|   MOZ_ASSERT(mFile.size() <= aLpofn->nMaxFile);
 | |
|   memcpy(aLpofn->lpstrFile,
 | |
|          mFile.data(), mFile.size() * sizeof(wchar_t));
 | |
|   if (aLpofn->lpstrFileTitle != nullptr) {
 | |
|     MOZ_ASSERT(mFileTitle.size() + 1 < aLpofn->nMaxFileTitle);
 | |
|     wcscpy(aLpofn->lpstrFileTitle, mFileTitle.c_str());
 | |
|   }
 | |
|   aLpofn->nFileOffset = mFileOffset;
 | |
|   aLpofn->nFileExtension = mFileExtension;
 | |
| }
 | |
| 
 | |
| void
 | |
| IPCSchannelCred::CopyFrom(const PSCHANNEL_CRED& aSCred)
 | |
| {
 | |
|   // We assert that the aSCred fields take supported values.
 | |
|   // If they do not then we ignore the values we were given.
 | |
|   MOZ_ASSERT(aSCred->dwVersion == SCHANNEL_CRED_VERSION);
 | |
|   MOZ_ASSERT(aSCred->cCreds == 0);
 | |
|   MOZ_ASSERT(aSCred->paCred == nullptr);
 | |
|   MOZ_ASSERT(aSCred->hRootStore == nullptr);
 | |
|   MOZ_ASSERT(aSCred->cMappers == 0);
 | |
|   MOZ_ASSERT(aSCred->aphMappers == nullptr);
 | |
|   MOZ_ASSERT(aSCred->cSupportedAlgs == 0);
 | |
|   MOZ_ASSERT(aSCred->palgSupportedAlgs == nullptr);
 | |
|   MOZ_ASSERT((aSCred->grbitEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS) ==
 | |
|              aSCred->grbitEnabledProtocols);
 | |
|   mEnabledProtocols =
 | |
|     aSCred->grbitEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS;
 | |
|   mMinStrength = aSCred->dwMinimumCipherStrength;
 | |
|   mMaxStrength = aSCred->dwMaximumCipherStrength;
 | |
|   MOZ_ASSERT(aSCred->dwSessionLifespan == 0);
 | |
|   MOZ_ASSERT((aSCred->dwFlags & SCHANNEL_SUPPORTED_FLAGS) == aSCred->dwFlags);
 | |
|   mFlags = aSCred->dwFlags & SCHANNEL_SUPPORTED_FLAGS;
 | |
|   MOZ_ASSERT(aSCred->dwCredFormat == 0);
 | |
| }
 | |
| 
 | |
| void
 | |
| IPCSchannelCred::CopyTo(PSCHANNEL_CRED& aSCred) const
 | |
| {
 | |
|   // Validate values as they come from an untrusted process.
 | |
|   memset(aSCred, 0, sizeof(SCHANNEL_CRED));
 | |
|   aSCred->dwVersion = SCHANNEL_CRED_VERSION;
 | |
|   aSCred->grbitEnabledProtocols =
 | |
|     mEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS;
 | |
|   aSCred->dwMinimumCipherStrength = mMinStrength;
 | |
|   aSCred->dwMaximumCipherStrength = mMaxStrength;
 | |
|   aSCred->dwFlags = mFlags & SCHANNEL_SUPPORTED_FLAGS;
 | |
| }
 | |
| 
 | |
| void
 | |
| IPCInternetBuffers::CopyFrom(const LPINTERNET_BUFFERSA& aBufs)
 | |
| {
 | |
|   mBuffers.Clear();
 | |
| 
 | |
|   LPINTERNET_BUFFERSA inetBuf = aBufs;
 | |
|   while (inetBuf) {
 | |
|     MOZ_ASSERT(inetBuf->dwStructSize == sizeof(INTERNET_BUFFERSA));
 | |
|     Buffer* ipcBuf = mBuffers.AppendElement();
 | |
| 
 | |
|     ipcBuf->mHeader.SetIsVoid(inetBuf->lpcszHeader == nullptr);
 | |
|     if (inetBuf->lpcszHeader) {
 | |
|       ipcBuf->mHeader.Assign(inetBuf->lpcszHeader, inetBuf->dwHeadersLength);
 | |
|     }
 | |
|     ipcBuf->mHeaderTotal = inetBuf->dwHeadersTotal;
 | |
| 
 | |
|     ipcBuf->mBuffer.SetIsVoid(inetBuf->lpvBuffer == nullptr);
 | |
|     if (inetBuf->lpvBuffer) {
 | |
|       ipcBuf->mBuffer.Assign(static_cast<char*>(inetBuf->lpvBuffer),
 | |
|                              inetBuf->dwBufferLength);
 | |
|     }
 | |
|     ipcBuf->mBufferTotal = inetBuf->dwBufferTotal;
 | |
|     inetBuf = inetBuf->Next;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void
 | |
| IPCInternetBuffers::CopyTo(LPINTERNET_BUFFERSA& aBufs) const
 | |
| {
 | |
|   MOZ_ASSERT(!aBufs);
 | |
| 
 | |
|   LPINTERNET_BUFFERSA lastBuf = nullptr;
 | |
|   for (size_t idx = 0; idx < mBuffers.Length(); ++idx) {
 | |
|     const Buffer& ipcBuf = mBuffers[idx];
 | |
|     LPINTERNET_BUFFERSA newBuf =
 | |
|       static_cast<LPINTERNET_BUFFERSA>(moz_xcalloc(1, sizeof(INTERNET_BUFFERSA)));
 | |
|     if (idx == 0) {
 | |
|       aBufs = newBuf;
 | |
|     } else {
 | |
|       MOZ_ASSERT(lastBuf);
 | |
|       lastBuf->Next = newBuf;
 | |
|       lastBuf = newBuf;
 | |
|     }
 | |
| 
 | |
|     newBuf->dwStructSize = sizeof(INTERNET_BUFFERSA);
 | |
| 
 | |
|     newBuf->dwHeadersTotal = ipcBuf.mHeaderTotal;
 | |
|     if (!ipcBuf.mHeader.IsVoid()) {
 | |
|       newBuf->lpcszHeader =
 | |
|         static_cast<LPCSTR>(moz_xmalloc(ipcBuf.mHeader.Length()));
 | |
|       memcpy(const_cast<char*>(newBuf->lpcszHeader), ipcBuf.mHeader.Data(),
 | |
|              ipcBuf.mHeader.Length());
 | |
|       newBuf->dwHeadersLength = ipcBuf.mHeader.Length();
 | |
|     }
 | |
| 
 | |
|     newBuf->dwBufferTotal = ipcBuf.mBufferTotal;
 | |
|     if (!ipcBuf.mBuffer.IsVoid()) {
 | |
|       newBuf->lpvBuffer = moz_xmalloc(ipcBuf.mBuffer.Length());
 | |
|       memcpy(newBuf->lpvBuffer, ipcBuf.mBuffer.Data(),
 | |
|              ipcBuf.mBuffer.Length());
 | |
|       newBuf->dwBufferLength = ipcBuf.mBuffer.Length();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /* static */ void
 | |
| IPCInternetBuffers::FreeBuffers(LPINTERNET_BUFFERSA& aBufs)
 | |
| {
 | |
|   if (!aBufs) {
 | |
|     return;
 | |
|   }
 | |
|   while (aBufs) {
 | |
|     LPINTERNET_BUFFERSA temp = aBufs->Next;
 | |
|     free(const_cast<char*>(aBufs->lpcszHeader));
 | |
|     free(aBufs->lpvBuffer);
 | |
|     free(aBufs);
 | |
|     aBufs = temp;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void
 | |
| IPCPrintDlg::CopyFrom(const LPPRINTDLGW& aDlg)
 | |
| {
 | |
|   // DLP: Trouble -- my prior impl "worked" but didn't return anything
 | |
|   // AFAIR.  So... ???  But it printed a page!!!  How?!
 | |
|   MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
 | |
| }
 | |
| 
 | |
| void
 | |
| IPCPrintDlg::CopyTo(LPPRINTDLGW& aDlg) const
 | |
| {
 | |
|   MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
 | |
| }
 | |
| 
 | |
| } // namespace plugins
 | |
| } // namespace mozilla
 | |
| 
 | |
| #endif // defined(XP_WIN)
 |