Video of the week

I've found this great video and I recommend you to watch if you are interested in wireshark and filtering methods

Dyskrecja w Outlook'u

Dyskrecja w Outlook'u

Interfejsy COM to prawdziwe dobrodziejstwo Windows'a. Przy pomocy tych binariów można bowiem np. wysłać maila z Outlooka bez jego otwierania albo np. przejrzeć całą listę kontaktów. Interfejsy COM zawierają bowiem funkcje i można porównać je do klasy abstrakcyjnej języka C++ (należy dodać, że COM to technologia językowo niezależna).  Aby móc w pełni korzystać z tego wszystkiego należy najpierw przyswoić sobie pre-schemat postępowania z tymi bibliotekami ale nie o tym i nie teraz. Problem jest inny i tego rodzaju:

out1

klikam TAK:

out2

aż w końcu:

out3

 

 

Niestety, aby móc cokolwiek sensownego zrobić z Outlookiem z wykorzystaniem COM, trzeba (prawie)tak klikać. Mało tego, jeśli ktoś potrafi czytać, to istnieje duża szansa na to, że kliknie NIE jeśli to nie on jest autorem tych działań. Trochę padaka ale tym większa radocha kiedy za chwilę okaże się, że można to OBEJŚĆ.

Fragment kodu to działania na Outlooku bez jego uruchamiania:

 

  1. #include "stdio.h"
  2.  
  3. #import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" rename("EOF","EOFile")
  4. // TLib : Microsoft Office 11.0 Object Library : {2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}
  5.  
  6. #import "libid:00062FFF-0000-0000-C000-000000000046" rename("EOF","EOFile")
  7. // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
  8.  
  9. #include "windows.h"
  10.  
  11. using namespace Office;
  12.  
  13. int main()
  14. {
  15. CoInitialize(NULL);
  16. HRESULT hr;
  17.  
  18. Outlook::_ApplicationPtr m_OutlookAppPtr;
  19.  
  20. hr = m_OutlookAppPtr.CreateInstance( __uuidof(Outlook::Application) );
  21.  
  22. Outlook::OlDefaultFolders contacts = Outlook::OlDefaultFolders::olFolderContacts;
  23.  
  24. Outlook::MAPIFolderPtr m_OutlookMAPIFolder;
  25. m_OutlookMAPIFolder = m_OutlookAppPtr->GetNamespace( _bstr_t("MAPI") )->GetDefaultFolder( contacts );
  26.  
  27. Outlook::_ItemsPtr pItems;
  28. pItems = m_OutlookMAPIFolder->GetItems();
  29.  
  30. Outlook::_ContactItemPtr pContact;
  31. pContact = pItems->GetFirst();
  32. fprintf(stdout,"%s\n",(char*)pContact->GetEmail1Address());
  33.  
  34. pContact = pItems->GetNext();
  35. fprintf(stdout,"%s\n",(char*)pContact->GetEmail1Address());
  36.  
  37. CoUninitialize();
  38. return 0;
  39. }

 

 

 

W Outlooku mam obecnie tylko 2 kontakty bo z Outlooka w sumie w ogóle nie korzystam, ale trzeba przetestować kod więc coś tam w kontakty wrzuciłem. Ten kod pobiera z mojego Outlooka owe 2 kontakty i wyświetla je na konsoli - fajnie. Problem w tym, że aby wyświetlić kontakt, muszę za każdym razem klikać TAK! (patrz wyżej na photo).

 

Mój sposób na obejście problemu:

 

  1. #include "outlookHookLib.h"
  2. #include "windows.h"
  3.  
  4. #pragma data_seg("shared")
  5. HHOOK hOutlook = NULL;
  6. HINSTANCE hInst = NULL;
  7. #pragma data_seg()
  8. #pragma comment(linker, "/SECTION:shared,RWS")
  9.  
  10. BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
  11. {
  12. if(fwdreason == DLL_PROCESS_ATTACH)
  13. hInst = hinstDLL;
  14.  
  15. return 1;
  16. }
  17.  
  18. __declspec(dllexport) LRESULT CALLBACK CBThookProc(int nCode, WPARAM wParam, LPARAM lParam)
  19. {
  20. if( ( nCode < 0 ) || ( nCode != HCBT_SETFOCUS ) )
  21. CallNextHookEx( NULL, nCode, wParam, lParam );
  22.  
  23. HWND hWindow = NULL;
  24.  
  25. if( ( hWindow = FindWindow( NULL, L"Microsoft Office Outlook" ) ) )
  26. {
  27. keybd_event( VK_TAB, 0x0F, 0, NULL );
  28. SendMessage( hWindow, WM_KEYDOWN, wParam, lParam );
  29.  
  30. keybd_event( VK_TAB, 0x0F, KEYEVENTF_KEYUP, NULL );
  31. SendMessage( hWindow, WM_KEYUP, wParam, lParam );
  32.  
  33. keybd_event( VK_TAB, 0x0F, 0, NULL );
  34. SendMessage( hWindow, WM_KEYDOWN, wParam, lParam );
  35.  
  36. keybd_event( VK_TAB, 0x0F, KEYEVENTF_KEYUP, NULL );
  37. SendMessage( hWindow, WM_KEYUP, wParam, lParam );
  38.  
  39. keybd_event( VK_TAB, 0x0F, 0, NULL );
  40. SendMessage( hWindow, WM_KEYDOWN, wParam, lParam );
  41.  
  42. keybd_event( VK_TAB, 0x0F, KEYEVENTF_KEYUP, NULL );
  43. SendMessage( hWindow, WM_KEYUP, wParam, lParam );
  44.  
  45. keybd_event( VK_RETURN, 0x1C, 0, NULL );
  46. SendMessage( hWindow, WM_KEYDOWN, wParam, lParam );
  47.  
  48. keybd_event( VK_RETURN, 0x1C, KEYEVENTF_KEYUP, NULL );
  49. SendMessage( hWindow, WM_KEYUP, wParam, lParam );
  50. }
  51.  
  52. return 0L;
  53. }
  54.  
  55. __declspec(dllexport) BOOL installOutlookHook(void )
  56. {
  57. hOutlook = SetWindowsHookEx( WH_CBT, (HOOKPROC)CBThookProc, hInst, 0 );
  58.  
  59. return 0;
  60. }
  61.  
  62. __declspec(dllexport) BOOL UninstallOutlookHook(void )
  63. {
  64. UnhookWindowsHookEx( hOutlook );
  65.  
  66. return 0;
  67. }

 

 

Tworzę bibliotekę outlookHookLib.dll i używam w niej ciekawej funkcji filtrującej CBThookProc(). Funkcja sprawdza w systemie obecność okna z tytułem "Microsoft Office Outlook" (tytuł ten sam, który pojawia się podczas uruchamiania Outlooka - istnieje zatem droba szansa kolizji okien i działania funkcji w kontekście nie tego okna co potrzeba - ale wystarczy dodatkowo sparametryzować funkcję filtrującą np poprzez sprawdzanie wymiaru okna komunikatu, jest ono stałe i dużo mniejsze niż okno programu Office Outlook ). Jeśli takie okno istnieje to dążymy do jego szybkiego zamknięcia. Okno nie zaczyna żyć kiedy jest widoczne na ekranie. Okno powstaje dużo wcześniej, co więcej nie musi być ono widoczne na ekranie a i tak może istnieć w systemie - ten fakt wykorzystamy. Jak tylko w systemie pojawi się to okno - nie na ekranie - wyślemy do niego komunikaty: WM_KEYDOWN i WM_KEYUP wykorzystując funkcje keybd_event() oraz SendMessage().

Pierwsza powoduje wygenerowanie komunikatów WM_KEYDOWN i WM_KEYUP a drugą funkcję wykorzystamy do przesłania tych klawiszy do okna komunikatu. Co to znaczy? To znaczy, że powiemy Windowsowi, żeby nacisnął za nas 3 razy TAB i na końcu ENTER. Wszystkie klawisze trafią do tego okna a to spowoduje, że zanim okno pojawi się na ekranie zostanie przez nas w magiczny, legalny sposób zamknięte! Wiadomo, trzykrotne naciśnięcie TAB spowoduje przejście 'FOCUSa' na button z Caption: 'TAK' a Enter tylko potwierdza (zezwala). Lista kontaktów wyświetli się bez jakiejkolwiek ingerencji osoby trzeciej.

Podsumowanie: W ten sam sposób możemy wyciągnąć całą listę kontaktów z odpowiedniego katalogu. Generalnie z Outlooka nie korzystam bardziej niż wcześniej. Przechowywanie poczty na dysku lokalnym to nie jest best idea tym bardziej, że Microsoft opublikował dokumentację formatu pliku *.PST no i dochodzi biblioteka mso.dll oraz COM etc.