mapirule.cpp
上传用户:baijia
上传日期:2022-05-22
资源大小:24k
文件大小:23k
源码类别:

手机短信编程

开发平台:

Visual C++

  1. //
  2. // Copyright (c) Microsoft Corporation.  All rights reserved.
  3. //
  4. //
  5. // Use of this sample source code is subject to the terms of the Microsoft
  6. // license agreement under which you licensed this sample source code. If
  7. // you did not accept the terms of the license agreement, you are not
  8. // authorized to use this sample source code. For the terms of the license,
  9. // please see the license agreement between you and Microsoft or, if applicable,
  10. // see the LICENSE.RTF on your install media or the root of your tools installation.
  11. // THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
  12. //
  13. // ************************************************************
  14. // MAPIRULE.CPP
  15. // 
  16. // Sample implementation of a message Rule Client
  17. //
  18. //
  19. #define INITGUID
  20. #include "windows.h"
  21. #include "cemapi.h"
  22. int g_cServerLocks = 0;
  23. // {3AB4C10E-673C-494c-98A2-CC2E91A48115}
  24. DEFINE_GUID(CLSID_MapiRuleSample, 0x3ab4c10e, 0x673c, 0x494c, 0x98, 0xa2, 0xcc, 0x2e, 0x91, 0xa4, 0x81, 0x15);
  25. /* Add to apps.reg:
  26. [HKEY_CLASSES_ROOTCLSID{3AB4C10E-673C-494c-98A2-CC2E91A48115}InProcServer32]
  27. @="mapirule.dll"
  28. */
  29. /*
  30. Add this line too:
  31. [HKEY_LOCAL_MACHINESoftwareMicrosoftInboxSvcSMSRules]
  32. "{3AB4C10E-673C-494c-98A2-CC2E91A48115}"=dword:1
  33. */
  34. // **************************************************************************
  35. // Function Name: DeleteMessage
  36. //
  37. // Purpose: Delete a MAPI message
  38. // Arguments:
  39. // IN IMsgStore* pMsgStore - Message Store to delete from
  40. // IN IMessage* pMsg - ptr to message to be deleted
  41. // IN ULONG cbMsg - The size of lpMsg, in bytes
  42. // IN LPENTRYID lpMsg - The ENTRYID of the message
  43. // IN ULONG cbDestFolder - The size of lpDestFolder, in bytes
  44. // IN LPENTRYID lpDestFolder - The ENTRYID of the folder that incoming
  45. // messages are moved to
  46. // OUT ULONG *pulEventType - Combination of bit flags indicating the type if 
  47. // action performed on the message, deletion in this case
  48. // OUT MRCHANDLED *pHandled - Indicates the type of handling that occurred,
  49. // in this case we mark the message as handled, and do not pass it on 
  50. //
  51. // Return Values:  HRESULT depending on success of MAPI operations
  52. // Side effects:  
  53. // Description:  
  54. // This function deletes a given message from a given folder and 
  55. //  sets the proper notification event  
  56. HRESULT DeleteMessage(IMsgStore *pMsgStore, IMessage *pMsg, ULONG cbMsg, LPENTRYID lpMsg, ULONG cbDestFolder, 
  57.                         LPENTRYID lpDestFolder, ULONG *pulEventType, MRCHANDLED *pHandled)
  58. {
  59.     HRESULT hr = S_OK;
  60.     ENTRYLIST lst;
  61.     SBinary sbin;
  62.     IMAPIFolder *pFolder = NULL;
  63.     
  64.     // Delete it
  65.     hr = pMsgStore->OpenEntry(cbDestFolder, lpDestFolder, NULL, 0, NULL, (LPUNKNOWN *) &pFolder);
  66.     if (FAILED(hr))
  67.     {
  68.         RETAILMSG(TRUE, (TEXT("Couldn't get the folder!rn")));
  69.         goto Exit;
  70.     }
  71.     
  72.     lst.cValues = 1;
  73.     sbin.cb = cbMsg;
  74.     sbin.lpb = (LPBYTE) lpMsg;
  75.     lst.lpbin = &sbin;
  76.     hr = pFolder->DeleteMessages(&lst, NULL, NULL, 0); 
  77.     if (FAILED(hr))
  78.     {
  79.         RETAILMSG(TRUE, (TEXT("Couldn't delete messages!rn")));
  80.         goto Exit;
  81.     }
  82.     // Notification object lets listeners know we deleted this
  83. *pulEventType = fnevObjectDeleted;
  84. // Mark as handled and don't pass on
  85.     *pHandled = MRC_HANDLED_DONTCONTINUE;
  86.     
  87. Exit:
  88.     if (pFolder)
  89.     {
  90.         pFolder->Release();
  91.     }
  92.     
  93.     return hr;
  94. }
  95. // ************************************************************
  96. // Class CMailRuleClient - Implementation of IMailRuleClient
  97. //
  98. // Inheritance:
  99. //     IMailRuleClient IUnknown (Abstract)
  100. //
  101. // Purpose:
  102. //     This class serves as implementation for the IMailRuleClient
  103. //    interface and provides our Rule Client functionality.
  104. //    The Initialize method sets our permissions to interact
  105. //    with the message store, and the ProcesseMessage method
  106. //    defines how we handle incoming messages
  107. //
  108. // ************************************************************
  109. class CMailRuleClient : public IMailRuleClient
  110. {
  111. public:
  112.     CMailRuleClient();
  113.     ~CMailRuleClient();
  114.     
  115.     // IUnknown
  116.     STDMETHOD (QueryInterface)(REFIID iid, LPVOID *ppv);
  117.     STDMETHOD_(ULONG, AddRef)();
  118.     STDMETHOD_(ULONG, Release)();
  119.     // IMailRuleClient
  120.     MAPIMETHOD(Initialize)(
  121.             IMsgStore *pMsgStore,
  122.             MRCACCESS *pmaDesired
  123.             );
  124.             
  125.     MAPIMETHOD(ProcessMessage)(
  126.             IMsgStore *pMsgStore, 
  127.             ULONG cbMsg,
  128.             LPENTRYID lpMsg,
  129.             ULONG cbDestFolder,
  130.             LPENTRYID lpDestFolder,
  131.             ULONG *pulEventType,
  132.             MRCHANDLED *pHandled
  133.             );
  134. private:
  135.     long m_cRef;
  136. };
  137. // ************************************************************
  138. // Class CFactory - Class factory for CMailRuleClient objects
  139. //
  140. // Inheritance:
  141. //     IClassFactory IUnknown
  142. //
  143. // Purpose:
  144. //     This class provides a standard COM class factory implementation
  145. //    for CMailRuleClient
  146. //
  147. // ************************************************************
  148. class CFactory : public IClassFactory
  149. {
  150. public:
  151.     CFactory();
  152.     ~CFactory();
  153.     
  154.     // IUnknown
  155.     STDMETHOD (QueryInterface)(REFIID iid, LPVOID *ppv);
  156.     STDMETHOD_(ULONG, AddRef)();
  157.     STDMETHOD_(ULONG, Release)();
  158.     // IClassFactory interfaces
  159.     STDMETHOD (CreateInstance)(IUnknown *pUnknownOuter, const IID& iid, LPVOID *ppv);
  160.     STDMETHOD (LockServer)(BOOL bLock);
  161. private:
  162.     long m_cRef;
  163. };
  164. // **************************************************************************
  165. // Function Name: CFactory 
  166. // Purpose: Initializes CFactory object
  167. // Arguments:
  168. // Return Values:
  169. // Side effects:  
  170. // Description: 
  171. // Constructor for CFactory class. Initializes class members.
  172.  
  173. CFactory::CFactory()
  174. {
  175.     m_cRef = 1;
  176. }
  177. // **************************************************************************
  178. // Function Name: ~CFactory
  179. //
  180. // Purpose: Cleans up CFactory object
  181. // Arguments:
  182. // Return Values:
  183. // Side effects:  
  184. // Description:  
  185. // Destructor for CFactory object
  186. CFactory::~CFactory()
  187. {
  188. }
  189. // **************************************************************************
  190. // Function Name: QueryInterface
  191. // Purpose: Obtains caller's desired interface pointer if it is supported
  192. // Arguments:
  193. // IN IID& iid - Identifier for desired interface
  194. // OUT LPVOID *ppv - pointer to desired interface pointer
  195. // Return Values: HRESULT 
  196. // E_NOINTERFACE:  the requested interface is not supported
  197. // E_INVALIDARG: bad reference for out param
  198. // Side effects:  
  199. // Description:
  200. // Standard implementation of COM IUnknown::QueryInterface
  201.   
  202. STDMETHODIMP CFactory::QueryInterface(const IID& iid, LPVOID *ppv)
  203. {
  204.     HRESULT hr = E_NOINTERFACE;
  205.     if (!ppv)
  206.     {
  207.         return E_INVALIDARG;
  208.     }
  209.     
  210.     if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
  211.     {
  212.         *ppv = (LPVOID) this;
  213.     }
  214.     else
  215.     {
  216.         *ppv = NULL;
  217.     }
  218.     if (*ppv) 
  219.     {
  220.         ((LPUNKNOWN) *ppv)->AddRef();
  221.         hr = S_OK;
  222.     }
  223.     
  224.     return hr;
  225. }
  226. // **************************************************************************
  227. // Function Name: AddRef
  228. // Purpose: COM reference counting
  229. // Description:  
  230. // Implements IUnknown::Addref by adding 1 to the object's reference count
  231. ULONG CFactory::AddRef()
  232. {
  233.     RETAILMSG(TRUE, (TEXT("Factory Reference is now %drn"), m_cRef + 1));
  234.     return InterlockedIncrement(&m_cRef);
  235. }
  236. // **************************************************************************
  237. // Function Name: Release
  238. // Purpose: COM reference counting
  239. // Return Value: ULONG - reference count after decrementing 
  240. // Description:  
  241. // Implements IUnknown::Release by subtracting 1 from the object's reference count
  242. ULONG CFactory::Release()
  243. {
  244.     InterlockedDecrement(&m_cRef);
  245.     RETAILMSG(TRUE, (TEXT("Factory Reference is now %drn"), m_cRef));
  246.     
  247.     int nLocal = m_cRef;
  248.     if (!m_cRef) 
  249.     {
  250.         RETAILMSG(TRUE, (TEXT("CFactory Deleted!rn")));
  251.         delete this; 
  252.     }
  253.     return nLocal; 
  254. }
  255. // **************************************************************************
  256. // Function Name: CreateInstance
  257. // Purpose: Create a new instance of a COM object and return the specified
  258. // interface
  259. // Arguments: IN LPUNKNOWN pUnknownOuter - controlling outer for aggregation
  260. // IN REFIID iid - interface identifier GUID reference
  261. // OUT LPVOID *ppv - pointer to newly created interface pointer
  262. // Return Values: HRESULT, S_OK if successful, error otherwise
  263. // Side effects:  
  264. // Description:  
  265. STDMETHODIMP CFactory::CreateInstance(LPUNKNOWN pUnknownOuter, REFIID iid, LPVOID *ppv)
  266. {
  267.     CMailRuleClient *pClient = NULL;
  268.     HRESULT hr;
  269.     // No aggregation
  270.     if (pUnknownOuter)
  271.     {
  272.         hr = CLASS_E_NOAGGREGATION;
  273.         goto Error;
  274.     }
  275.     // You heard 'em, create a component
  276.     pClient = new CMailRuleClient();
  277.     if (!pClient)
  278.     {
  279.         hr = E_OUTOFMEMORY;
  280.         goto Error;
  281.     }
  282.     
  283.     // Get the requested interface
  284.     hr = pClient->QueryInterface(iid, ppv);
  285. Error:
  286.     // Release the unknown pointer
  287.     if (pClient) 
  288.     {
  289.         pClient->Release();
  290.     }
  291.     
  292.     return hr;
  293. }
  294. // **************************************************************************
  295. // Function Name: LockServer
  296. // Purpose: Increment or decrement the number of lock on a COM server
  297. // Arguments: IN BOOL bLock - increment(TRUE) or decrement(FALSE) the lockcount
  298. // Return Values: HRESULT - S_OK
  299. // Side effects:  
  300. // Description:  
  301. STDMETHODIMP CFactory::LockServer(BOOL bLock)
  302. {
  303.     if (bLock)
  304.     {
  305.         g_cServerLocks++;
  306.     }
  307.     else
  308.     {
  309.         g_cServerLocks--;
  310.     }
  311.     return S_OK;
  312. }
  313. // **************************************************************************
  314. // Function Name: CMailRuleClient
  315. //
  316. // Purpose: Initialize the CMailRuleClient object
  317. // Arguments: none
  318. // Return Values: none
  319. // Side effects:  
  320. // Description: CMailRuleClient Constructor 
  321. CMailRuleClient::CMailRuleClient()
  322. {
  323.     m_cRef = 1;
  324. }
  325. // **************************************************************************
  326. // Function Name: ~CMailRuleClient
  327. //
  328. // Purpose: Cleans up CMailRuleClient object
  329. // Arguments:
  330. // Return Values:
  331. // Side effects:  
  332. // Description:  
  333. // Destructor for CMailRuleClient object
  334. CMailRuleClient::~CMailRuleClient()
  335. {
  336. }
  337. // **************************************************************************
  338. // Function Name: QueryInterface
  339. // Purpose: Obtains caller's desired interface pointer if it is supported
  340. // Arguments:
  341. // IN IID& iid - Identifier for desired interface
  342. // OUT LPVOID *ppv - pointer to desired interface pointer
  343. // Return Values: HRESULT 
  344. // E_NOINTERFACE:  the requested interface is not supported
  345. // E_INVALIDARG: bad reference for out param
  346. // Side effects:  
  347. // Description:
  348. // Standard implementation of COM IUnknown::QueryInterface
  349. HRESULT CMailRuleClient::QueryInterface(REFIID rif, void** ppobj)
  350. {
  351.     HRESULT hr = E_NOINTERFACE;
  352.     if (!ppobj)
  353.     {
  354.         return E_INVALIDARG;
  355.     }
  356.     
  357. *ppobj = NULL;
  358. if ((rif == IID_IUnknown) || (rif == IID_IMailRuleClient))
  359. {
  360.   *ppobj = (LPVOID) this;
  361.   }
  362.     if (*ppobj) 
  363.     {
  364.   ((LPUNKNOWN) *ppobj)->AddRef();
  365. hr = S_OK;
  366. }
  367. return hr;
  368. }
  369. // **************************************************************************
  370. // Function Name: AddRef
  371. // Purpose: COM reference counting
  372. // Arguments: none
  373. // Return Values: current ref count (after adding)
  374. // Description:  
  375. // Implements IUnknown::Addref by adding 1 to the object's reference count
  376. ULONG CMailRuleClient::AddRef()
  377. {
  378.     RETAILMSG(TRUE, (TEXT("CMailRuleClient reference is now %drn"), m_cRef + 1));
  379.     return InterlockedIncrement(&m_cRef);
  380. }
  381. // **************************************************************************
  382. // Function Name: Release
  383. // Purpose: COM reference counting
  384. // Arguments: none
  385. // Return Values: current ref count (after subracting)
  386. // Side effects:  
  387. // Description:
  388. // Implements IUnknown::Addref by subtracting 1 from the object's reference count  
  389. ULONG CMailRuleClient::Release()
  390. {
  391.     InterlockedDecrement(&m_cRef);
  392.     RETAILMSG(TRUE, (TEXT("CMailRuleClient reference is now %drn"), m_cRef));
  393.     
  394.     int nLocal = m_cRef;
  395.     if (!m_cRef) 
  396.     {
  397.         RETAILMSG(TRUE, (TEXT("CMailRuleClient Deleted!rn")));
  398.         delete this; 
  399.     }
  400.     return nLocal; 
  401. }
  402. // **************************************************************************
  403. // Function Name: Initialize
  404. //
  405. // Purpose: determines how the mail rule client will process incoming messages.
  406. // Arguments: IN IMsgStore * pMsgStore - represests message store which contains
  407. // the incoming messages
  408. //   OUT MRCACCESS *pmaDesired - desired message store access level
  409. // Return Values: HRESULT - S_OK
  410. // Side effects:  
  411. // Description:  
  412. // This function is called by the system to initialize rule clients. Since we
  413. // eventually may want to delete messages, we request write access here
  414. HRESULT CMailRuleClient::Initialize(IMsgStore *pMsgStore, MRCACCESS *pmaDesired)
  415. {
  416.   
  417.     *pmaDesired = MRC_ACCESS_WRITE;
  418.     return S_OK;
  419. }
  420. // **************************************************************************
  421. // Function Name: ProcessMessage
  422. //
  423. // Purpose: process incoming messages, which can be moved, modified, or deleted 
  424. // Arguments: IN IMsgStore * pMsgStore - represests message store which contains
  425. // the incoming messages
  426. //   IN ULONG cbMsg - The size of lpMsg in bytes
  427. //   IN LPENTRYID - The ENTRYID of the message
  428. //   IN ULONG cbDestFolder - The size of lpDestFolder in bytes
  429. //   IN LPENTRYID lpDestFolder - The ENTRYID of the the folder that 
  430. // incoming messages are moved to.
  431. //   OUT ULONG * pulEventType - bit flag that indicates the type of 
  432. // action the client performed on the message 
  433. //   OUT MRCHANDLED * pHandled - The type of message handling that 
  434. // occured during the processing
  435. //   
  436. // Return Values: HRESULT 
  437. // This method returns S_OK if the processing was successful, and appropriate 
  438. // errors if not. 
  439. // Side effects:  
  440. // Description: 
  441. // This function is called by the system when an incoming message is received
  442. //  This is where all the plugin-defined processing happens. You can filter 
  443. // messages based on content, delete or move messages, and report whether the
  444. //  message has been handled or not.
  445. HRESULT CMailRuleClient::ProcessMessage(IMsgStore *pMsgStore, ULONG cbMsg, LPENTRYID lpMsg, 
  446.             ULONG cbDestFolder, LPENTRYID lpDestFolder, ULONG *pulEventType, MRCHANDLED *pHandled)
  447. {
  448. MessageBox(NULL, L"ProcessMessage", L"ProcessMessage", MB_OK);
  449.     HRESULT hr = S_OK;
  450.     SizedSPropTagArray(1, sptaSubject) = { 1, PR_SUBJECT}; 
  451.  SizedSPropTagArray(1, sptaEmail) = { 1, PR_SENDER_EMAIL_ADDRESS}; 
  452.     ULONG cValues = 0;
  453.     SPropValue *pspvSubject = NULL;
  454. SPropValue *pspvEmail = NULL;
  455.     IMessage *pMsg = NULL;
  456.     HRESULT hrRet = S_OK;
  457.     // Get the message from the entry ID
  458.     hr = pMsgStore->OpenEntry(cbMsg, lpMsg, NULL, 0, NULL, (LPUNKNOWN *) &pMsg);
  459.     if (FAILED(hr))
  460.     {
  461.         
  462. RETAILMSG(TRUE, (TEXT("Unable to get the message!rn")));
  463.        goto Exit;
  464.     }
  465.     
  466.     // For SMS, the subject is also the message body
  467.     hr = pMsg->GetProps((SPropTagArray *) &sptaSubject, MAPI_UNICODE, &cValues, &pspvSubject);
  468. if (FAILED(hr))
  469.     {
  470.         
  471. RETAILMSG(TRUE, (TEXT("Unable to get the message body!rn")));
  472.        goto Exit;
  473.     }
  474. // get the sender's address or phone number
  475. hr = pMsg->GetProps((SPropTagArray *) &sptaEmail, MAPI_UNICODE, &cValues, &pspvEmail);
  476.     if (FAILED(hr))
  477.     {
  478.         
  479.         RETAILMSG(TRUE, (TEXT("Couldn't get the sender's address!rn")));
  480.         goto Exit;
  481.     }
  482. // Here we filter the message on some predetermined string. For sample purposes
  483. // here we use "zzz". What happens when the filter condition(s) are met is up to
  484. // you. You can send WM_COPYDATA messages to other app windows for light IPC, send
  485. // an SMS message in response, or whatever you need to do. Here, we just play a
  486. // sound and show the message in a standard message box.
  487. //if (wcsstr(pspvSubject->Value.lpszW, L"zzz") != NULL)
  488. if (wcsstr(pspvEmail->Value.lpszW, L"14250010001") != NULL)
  489. {
  490. MessageBeep(MB_ICONASTERISK);
  491. MessageBox(NULL, pspvSubject->Value.lpszW, pspvEmail->Value.lpszW, MB_OK);
  492. // Delete the message and mark it as handled so it won't show up in Inbox
  493. hr = DeleteMessage(pMsgStore, pMsg, cbMsg, lpMsg, cbDestFolder, lpDestFolder, pulEventType, pHandled);
  494. }
  495. else 
  496. {
  497. // a 'normal' message, pass it on
  498. *pHandled = MRC_NOT_HANDLED;
  499. }
  500. // Clean up
  501. Exit:
  502.     if (pspvEmail)
  503.     {
  504.         MAPIFreeBuffer(pspvEmail);
  505.     }
  506. if (pspvSubject)
  507.     {
  508.         MAPIFreeBuffer(pspvSubject);
  509.     }
  510.     if (pMsg)
  511.     {
  512.         pMsg->Release();
  513.     }
  514.     
  515.     return hr;
  516. }
  517. // **************************************************************************
  518. // Function Name: DllMain
  519. // Purpose: DLL Entry point
  520. // Arguments: IN HANDLE hinst - Handle to the DLL
  521. //   IN DWORD dwReason - flag indicating why entry-point was called
  522. //   IN LPVOID lpv - specifies further aspects of initialization and
  523. // cleanup 
  524. // Return Values: TRUE if initialization succeeds, FALSE otherwise
  525. // Side effects:  
  526. // Description: 
  527. // Called by system when a thread or process loads/unloads the dll 
  528. BOOL WINAPI DllMain(HANDLE hinst, DWORD dwReason, LPVOID lpv)
  529. {
  530.    MessageBox(NULL, L"dll main", L"dll main", MB_OK);
  531. switch (dwReason)
  532.     {
  533.         case DLL_PROCESS_ATTACH:
  534.             break;
  535.         case DLL_PROCESS_DETACH:
  536.             break;
  537.         default:
  538.             break;
  539.     }
  540.     return TRUE;
  541. }
  542. // **************************************************************************
  543. // Function Name: DllGetClassObject
  544. // Purpose: Retrieves the class object from the DLL object
  545. // Arguments: IN CLSID& clsid - CLSID for desired class object
  546. //   IN REFIID iid - ref to interface id, usually IClassFactory
  547. //   OUT LPVOID *ppv - address of requested interface pointer
  548. // Return Values: HRESULT
  549. // Side effects:  
  550. // Description:  
  551. STDAPI DllGetClassObject(const CLSID& clsid, REFIID iid, LPVOID *ppv)
  552. {
  553.     HRESULT hr;
  554.     
  555.     // We only understand this rule's class
  556.     if (clsid != CLSID_MapiRuleSample)
  557.     {
  558.         return CLASS_E_CLASSNOTAVAILABLE;
  559.     }
  560.     CFactory *pFactory = new CFactory;
  561.     if (!pFactory)
  562.     {
  563.         return E_OUTOFMEMORY;
  564.     }
  565.     // Get the requested interface
  566.     hr = pFactory->QueryInterface(iid, ppv);
  567.     pFactory->Release();
  568.     
  569.     return hr;
  570. }
  571. // **************************************************************************
  572. // Function Name: DllCanUnloadNow
  573. //
  574. // Purpose: Notify caller if dll can safely be unloaded
  575. // Arguments: none
  576. // Return Values: HRESULT, S_OK if safe to unload, S_FALSE otherwise
  577. // Side effects:  
  578. // Description:  A call to DllCanUnloadNow determines whether the DLL from 
  579. // which it is exported is still in use. A DLL is no longer in use when it 
  580. // is not managing any existing objects (the reference count on all of its 
  581. // objects is zero). 
  582. STDAPI DllCanUnloadNow()
  583. {
  584.     if (!g_cServerLocks)
  585.     {
  586.      
  587.         return S_OK;
  588.     }
  589.     else
  590.     {
  591.         return S_FALSE;
  592.     }
  593. }
  594. // **************************************************************************
  595. // Function Name: DllRegisterServer
  596. //
  597. // Purpose: provide DLL with the ability to register its COM objects
  598. // Arguments: none
  599. // Return Values: HRESULT - S_OK if registration succeeds, E_FAIL otherwise
  600. // Side effects: In order to fully remove the plugin, both registry keys should
  601. // be removed (see Description below). DllUnregisterServer does this.
  602. // Description:  
  603. //  In addition to standard COM object registration, the function also must
  604. //  register our rule client handler with Inbox.  We are registering our 
  605. // DLL in two places, HKEY_CLASSES_ROOTCLSID, and HKEY_LOCAL_MACHINESoftware
  606. // MicrosoftInboxSvcSMSRules
  607. STDAPI DllRegisterServer()
  608. {
  609.     LRESULT lr;
  610.     HRESULT hr = E_FAIL;
  611.     HKEY hKey = NULL;
  612.     HKEY hSubKey = NULL;
  613.     DWORD dwDisposition;
  614.     TCHAR wszValue[20];
  615.     // Set up registry keys
  616.     // Register with COM:
  617.     //    [HKEY_CLASSES_ROOTCLSID{3AB4C10E-673C-494c-98A2-CC2E91A48115}InProcServer32]
  618.     //    @="mapirule.dll"
  619.     lr = RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("\CLSID\{3AB4C10E-673C-494c-98A2-CC2E91A48115}"),
  620.                               0, NULL, 0, 0, NULL, 
  621.                               &hKey, &dwDisposition);
  622.     if (lr != ERROR_SUCCESS)
  623.     {
  624.         goto Exit;
  625.     }
  626.     lr = RegCreateKeyEx(hKey, TEXT("InprocServer32"),
  627.                               0, NULL, 0, 0, NULL, 
  628.                               &hSubKey, &dwDisposition);
  629.     if (lr != ERROR_SUCCESS)
  630.     {
  631.         goto Exit;
  632.     }
  633.     lstrcpy(wszValue, TEXT("mapirule.dll"));
  634.     lr = RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (LPBYTE) wszValue, (lstrlen(wszValue) + 1) * sizeof(TCHAR));
  635.     if (lr != ERROR_SUCCESS)
  636.     {
  637.         goto Exit;
  638.     }
  639.     RegCloseKey(hSubKey);
  640.     hSubKey = NULL;
  641.     RegCloseKey(hKey);
  642.     hKey = NULL;
  643.     // Register with Inbox:
  644.     //    [HKEY_LOCAL_MACHINESoftwareMicrosoftInboxSvcSMSRules]
  645.     //    {3AB4C10E-673C-494c-98A2-CC2E91A48115}"=dword:1
  646.     lr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("\Software\Microsoft\Inbox\Svc\SMS\Rules"),
  647.                               0, NULL, 0, 0, NULL, 
  648.                               &hKey, &dwDisposition);
  649.     if (lr != ERROR_SUCCESS)
  650.     {
  651.         goto Exit;
  652.     }
  653.     dwDisposition = 1;
  654.     lr = RegSetValueEx(hKey, TEXT("{3AB4C10E-673C-494c-98A2-CC2E91A48115}"), 0, REG_DWORD, 
  655.                           (LPBYTE) &dwDisposition, sizeof(DWORD));
  656.     if (lr != ERROR_SUCCESS)
  657.     {
  658.         goto Exit;
  659.     }
  660.  
  661.     hr = S_OK;
  662. Exit:
  663.     if (hSubKey)
  664.     {
  665.         RegCloseKey(hSubKey);
  666.     }
  667.     if (hKey)
  668.     {
  669.         RegCloseKey(hKey);
  670.     }
  671.     return hr;
  672. }
  673. // **************************************************************************
  674. // Function Name: DllUnregisterServer
  675. // Purpose: rovide DLL with the ability to un-register its COM objects
  676. // Arguments: none
  677. // Return Values: HRESULT - S_OK if registration succeeds, E_FAIL otherwise
  678. // Side effects: 
  679. // Description:  Deletes both the COM registry key and the key used to register
  680. // the rule client with Inbox
  681. STDAPI DllUnregisterServer()
  682. {
  683.     HKEY hKey = NULL;
  684.     HRESULT hr = E_FAIL;
  685.     LRESULT lr;
  686.     DWORD dwDisposition;
  687.     // Delete registry keys
  688.     RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("\CLSID\{3AB4C10E-673C-494c-98A2-CC2E91A48115}"));
  689.     
  690.     lr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("\Software\Microsoft\Inbox\Svc\SMS\Rules"),
  691.                               0, NULL, 0, 0, NULL, 
  692.                               &hKey, &dwDisposition);
  693.     if (lr != ERROR_SUCCESS)
  694.     {
  695.         goto Exit;
  696.     }
  697.     RegDeleteValue(hKey, TEXT("{3AB4C10E-673C-494c-98A2-CC2E91A48115}"));
  698.     hr = S_OK;
  699. Exit:
  700.     if (hKey)
  701.     {
  702.         RegCloseKey(hKey);
  703.     }
  704.     return hr;
  705. }