-
-
Notifications
You must be signed in to change notification settings - Fork 615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Outlook: inProcess implementation to report replied / replied all / forwarded status on mail items in the message list #8756
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
a290640
Outlook: report replied / replied all / forwarded status on mail item…
michaelDCurran 13cf35c
Add translator comments.
michaelDCurran 3fd8fd2
Fix typo in comment.
michaelDCurran ada9b18
nvdaHelperRemote, outlook_getMAPIProperty: return any error code fro…
michaelDCurran 663158e
Fix case of path.
michaelDCurran da9fb4c
nvdaHelperRemote, outlook_getMAPIProperty: try HrGetOneProp before Hr…
michaelDCurran c8c2d8c
NVDAHelperRemote, outlook_getMAPIProperty: check result of IGlobalInt…
michaelDCurran aaf0c1c
outlook_getMAPIProperty: fix logging.
michaelDCurran 4d74915
NvDAHelperRemote, inProcess_getMessageHook: wParam can have flags oth…
michaelDCurran 7015b63
Address review comments.
michaelDCurran 150970d
Address further review comments.
michaelDCurran a71adc1
Update what's new
michaelDCurran File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
This file is a part of the NVDA project. | ||
Copyright 2018 NV Access Limited. | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License version 2.0, as published by | ||
the Free Software Foundation. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
This license can be found at: | ||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <windows.h> | ||
|
||
// A Smart Library handle. | ||
// Construct it with a handle returned by LoadLibrary or similar. | ||
// Once the object goes out of scope, FreeLibrary will automatically be called on the handle. | ||
class CLoadedLibrary { | ||
private: | ||
HMODULE _hModule {nullptr}; | ||
CLoadedLibrary(const CLoadedLibrary&)=delete; | ||
const CLoadedLibrary& operator=(const CLoadedLibrary&)=delete; | ||
|
||
public: | ||
|
||
CLoadedLibrary(HMODULE h): _hModule(h) {}; | ||
|
||
void free() { | ||
if(_hModule) { | ||
FreeLibrary(_hModule); | ||
_hModule=nullptr; | ||
} | ||
} | ||
|
||
CLoadedLibrary& operator=(HMODULE h) { | ||
free(); | ||
_hModule=h; | ||
return *this; | ||
} | ||
|
||
operator HMODULE() { | ||
return _hModule; | ||
} | ||
|
||
operator bool() { | ||
return static_cast<bool>(_hModule); | ||
} | ||
|
||
~CLoadedLibrary() { | ||
free(); | ||
} | ||
|
||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* | ||
This file is a part of the NVDA project. | ||
Copyright 2018 NV Access Limited. | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License version 2.0, as published by | ||
the Free Software Foundation. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
This license can be found at: | ||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html | ||
*/ | ||
|
||
#define WIN32_LEAN_AND_MEAN | ||
|
||
#include <memory> | ||
#include <comdef.h> | ||
#include <windows.h> | ||
#include <common/log.h> | ||
#include <common/libraryLoader.h> | ||
#include "inProcess.h" | ||
#include "nvdaInProcUtils.h" | ||
|
||
// The following declarations come from MAPIDEFS.h which is no longer included in the Windows SDK | ||
|
||
constexpr ULONG PT_LONG=3; | ||
constexpr ULONG MAPI_E_NOTFOUND=0x8004010f; | ||
constexpr ULONG PROP_TYPE_MASK=0xffff; | ||
|
||
typedef struct { | ||
ULONG ulPropTag; | ||
ULONG dwAlignPad; | ||
union { | ||
long l; | ||
// other types removed | ||
} Value; | ||
} SPropValue; | ||
|
||
using funcType_HrGetOneProp=HRESULT(STDAPICALLTYPE *)(IUnknown*,ULONG,SPropValue**); | ||
using funcType_MAPIFreeBuffer=ULONG(STDAPICALLTYPE *)(SPropValue*); | ||
|
||
// Our RPC function | ||
error_status_t nvdaInProcUtils_outlook_getMAPIProp(handle_t bindingHandle, const long threadID, IUnknown* mapiObject, const unsigned long mapiPropTag, VARIANT* retVal) { | ||
if(!mapiObject) { | ||
LOG_ERROR(L"NULL MAPI object"); | ||
return E_INVALIDARG; | ||
} | ||
if((mapiPropTag&PROP_TYPE_MASK)!=PT_LONG) { | ||
// Right now this function only supports MAPI properties with a type of long. | ||
// To support more types, we would need to know how to correctly pack them into a VARIANT. | ||
LOG_ERROR(L"Unsupported MAPI prop type"); | ||
return E_INVALIDARG; | ||
} | ||
// Load mapi32 and manually lookup the functions we need. | ||
CLoadedLibrary mapi32lib=LoadLibrary(L"mapi32.dll"); | ||
if(!mapi32lib) { | ||
LOG_ERROR(L"Could not load mapi32.dll"); | ||
return E_UNEXPECTED; | ||
} | ||
auto HrGetOneProp=(funcType_HrGetOneProp)GetProcAddress(mapi32lib,"HrGetOneProp"); | ||
if(!HrGetOneProp) { | ||
// Some versions of mapi32.dll name the HrGetOneProp symbol with an arguments size suffix | ||
HrGetOneProp=(funcType_HrGetOneProp)GetProcAddress(mapi32lib,"HrGetOneProp@12"); | ||
} | ||
if(!HrGetOneProp) { | ||
LOG_ERROR(L"Could not locate function HrGetOneProp in mapi32.dll"); | ||
return E_UNEXPECTED; | ||
} | ||
auto MAPIFreeBuffer=(funcType_MAPIFreeBuffer)GetProcAddress(mapi32lib,"MAPIFreeBuffer"); | ||
if(!MAPIFreeBuffer) { | ||
LOG_ERROR(L"Could not locate function MAPIFreeBuffer in mapi32.dll"); | ||
return E_UNEXPECTED; | ||
} | ||
// NVDA gave us an IUnknown pointer representing the MAPI object from Outlook. | ||
// As the MAPIProp interface is not marshallable, we need to access it from its original STA thread as a real (non-proxied) raw pointer. | ||
// Therefore register the IUnknown in the COM global interface table so we can unmarshal it in the main GUI thread. | ||
IGlobalInterfaceTablePtr pGIT; | ||
HRESULT res=pGIT.CreateInstance(CLSID_StdGlobalInterfaceTable); | ||
if(res!=S_OK) { | ||
LOG_ERROR(L"Could not create global interface table"); | ||
return res; | ||
} | ||
DWORD cookie=0; | ||
res=pGIT->RegisterInterfaceInGlobal(mapiObject,IID_IUnknown,&cookie); | ||
if(res!=S_OK) { | ||
LOG_ERROR(L"Could not register object in global interface table"); | ||
return res; | ||
} | ||
// Execute the following code in Outlook's GUI thread. | ||
execInThread(threadID,[=,&res](){ | ||
// Unmarshal the IUnknown pointer from the COM global interface table. | ||
IUnknownPtr mapiObject=nullptr; | ||
res=pGIT->GetInterfaceFromGlobal(cookie,IID_IUnknown,reinterpret_cast<void**>(&mapiObject)); | ||
if(res!=S_OK) { | ||
LOG_ERROR(L"Could not unmarshal object, code "<<res); | ||
return; | ||
} | ||
// Fetch the wanted property from the MAPI object | ||
std::unique_ptr<SPropValue,funcType_MAPIFreeBuffer> propValue {nullptr,MAPIFreeBuffer}; | ||
{ | ||
SPropValue* _propValue=nullptr; | ||
res=HrGetOneProp(mapiObject,mapiPropTag,&_propValue); | ||
propValue.reset(_propValue); | ||
} | ||
if(res!=S_OK) { | ||
// We should be quiet about the error where the property does not exist as this happens most of the time. | ||
if(res!=MAPI_E_NOTFOUND) LOG_ERROR(L"Could not fetch MAPI property, code "<<res); | ||
return; | ||
} | ||
if(!propValue) { | ||
LOG_ERROR(L"NULL property value"); | ||
res=E_UNEXPECTED; | ||
return; | ||
} | ||
// Pack the property value into the VARIANT for returning. | ||
// We can assume here that the type is long and nothing else. | ||
retVal->vt=VT_I4; | ||
retVal->lVal=propValue->Value.l; | ||
}); | ||
// Unregister the IUnknown from the COM global interface table as we don't need it anymore. | ||
pGIT->RevokeInterfaceFromGlobal(cookie); | ||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this equal to
if(code<0||wParam~PM_REMOVE) {
I consider that to be somewhat more readble, but that's just a personal preference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
~ in c++ is a unary operator I think. So it would have to be wParam&~PM_REMOVE.