|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
MAPI profiles and corrupt registryWe are facing a very strange problem with Extended MAPI. We have a multi threaded Windows service (ATL). The service is able to connect to all mailboxes in the organization. For this a new MAPI profile is created (permanent) with a unique name. The profile is used to connect to the mailbox, do the action on the mailbox and then logoff is called. The MAPI profile is immediately deleted after the logoff. This is working correctly, however after some time (weekly or monthly) strange thing happens: the service is not able to log on to any mailbox and the registry key (the service runs under a specific account) HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles can't be opened anymore. It is not possible to open or delete the registry key. I have searched for an open handle among the running processes for this registry key, but there was none. The registry key can only be deleted after a reboot. After the reboot the same situation can be reproduced at least once a month. I must add that the number of profiles created/deleted per day can exceed the number 100000. When the registry key gets corrupted, it is not possible to call MAPIInitialize - it returns MAPI_E_NOT_INITIALIZED. The MAPI32.dll is the one from the Exchange System Manager. No Outlook is installed. Is there any known issue with this registry key? Is there a way to restart the MAPI subsystem without restarting the server? Thank you very much. Is your code executed on the saee thread? If yes, why do you need to call
MAPIInitialize multiple times? Did you monitor the number of handles and memory usage of the process? Sounds llike you have a reference leak somewhere in you code... Dmitry Streblechenko (MVP) http://www.dimastr.com/ OutlookSpy - Outlook, CDO and MAPI Developer Tool Show quote "Vladimir Werskov" <Vladimir Wers***@discussions.microsoft.com> wrote in message news:A5189D9E-2533-4839-ACF7-0C334A27D5E6@microsoft.com... > Hello to all. > > We are facing a very strange problem with Extended MAPI. We have a multi > threaded Windows service (ATL). The service is able to connect to all > mailboxes in the organization. For this a new MAPI profile is created > (permanent) with a unique name. The profile is used to connect to the > mailbox, do the action on the mailbox and then logoff is called. The MAPI > profile is immediately deleted after the logoff. > > This is working correctly, however after some time (weekly or monthly) > strange thing happens: the service is not able to log on to any mailbox > and > the registry key (the service runs under a specific account) > > HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging > Subsystem\Profiles > > can't be opened anymore. It is not possible to open or delete the registry > key. I have searched for an open handle among the running processes for > this > registry key, but there was none. The registry key can only be deleted > after > a reboot. > After the reboot the same situation can be reproduced at least once a > month. > I must add that the number of profiles created/deleted per day can exceed > the > number 100000. > When the registry key gets corrupted, it is not possible to call > MAPIInitialize - it returns MAPI_E_NOT_INITIALIZED. > The MAPI32.dll is the one from the Exchange System Manager. No Outlook is > installed. > > Is there any known issue with this registry key? > Is there a way to restart the MAPI subsystem without restarting the > server? > > Thank you very much. > Hello,
first, thanks for the answer. To make things clear: When the service starts, it calls MAPIInitialize on the main thread. When the service is shut down it calls MAPIUninitialize. This is needed to keep the MAPI subsystem alive until my threads are working. In the service's PreMessageLoop (ATL 7) the MAPI_Initialize method is called. bool CServiceModule::MAPI_Initialize() { HRESULT hr = S_OK; MAPIINIT_0 MAPIINIT = {0, MAPI_MULTITHREAD_NOTIFICATIONS | MAPI_NT_SERVICE | MAPI_NO_COINIT}; hr = MAPIInitialize(&MAPIINIT);if (FAILED(hr)) { LogEvent(_T("Error: MAPI_Initialize >> %08X\n"), hr); return false; } return true; } Then in the PostMessageLoop the MAPIUninitialize is called to release the last reference to MAPI. When one of the service interfaces is called, it actually creates a new COM object (implemented by a COM DLL), which calls MAPIInitialize (same parameters as above) in the constructor. The COM objects are always used by only one thread, but multiple threads can create their own objects. In the destructor of the COM object, the MAPIUninitialize is called. On the target systems, the service is restarted at least once a day - in this case the service stops without errors. But the registry still gets corrupted. So the corruption occurs independently of whether the service is running or not. There is no other application which is using MAPI so after the service terminates, the resources (also the possible leaked ones) should be released, right? I have at least 5 years of experience with MAPI programming, but this is something which makes me crazy. No matter how you fine tune your applications, guard them by external applications, it gets stuck and the whole system must be restarted. If there whould be a workaround or possibility to delete the corrupted registry key - i would be happy. Show quote "Dmitry Streblechenko" wrote: > Is your code executed on the saee thread? If yes, why do you need to call > MAPIInitialize multiple times? > Did you monitor the number of handles and memory usage of the process? > Sounds llike you have a reference leak somewhere in you code... > > Dmitry Streblechenko (MVP) > http://www.dimastr.com/ > OutlookSpy - Outlook, CDO > and MAPI Developer Tool Hmmm... I don't know. I can omly suggest the standard technique of
commenting your code and bringing it back until the problem manifetss itself. Dmitry Streblechenko (MVP) http://www.dimastr.com/ OutlookSpy - Outlook, CDO and MAPI Developer Tool Show quote "Vladimir Werskov" <Vladimir Wers***@discussions.microsoft.com> wrote in message news:ECF2F526-43E7-48F9-A548-E6DDBFD97BBA@microsoft.com... > Hello, > > first, thanks for the answer. > To make things clear: > > When the service starts, it calls MAPIInitialize on the main thread. When > the service is shut down it calls MAPIUninitialize. This is needed to keep > the MAPI subsystem alive until my threads are working. > > In the service's PreMessageLoop (ATL 7) the MAPI_Initialize method is > called. > > bool CServiceModule::MAPI_Initialize() > { > HRESULT hr = S_OK; > MAPIINIT_0 MAPIINIT = {0, MAPI_MULTITHREAD_NOTIFICATIONS | MAPI_NT_SERVICE > | MAPI_NO_COINIT}; > > hr = MAPIInitialize(&MAPIINIT); > if (FAILED(hr)) > { > LogEvent(_T("Error: MAPI_Initialize >> %08X\n"), hr); > return false; > } > return true; > } > > Then in the PostMessageLoop the MAPIUninitialize is called to release the > last reference to MAPI. > > When one of the service interfaces is called, it actually creates a new > COM > object (implemented by a COM DLL), which calls MAPIInitialize (same > parameters as above) in the constructor. The COM objects are always used > by > only one thread, but multiple threads can create their own objects. In the > destructor of the COM object, the MAPIUninitialize is called. > > On the target systems, the service is restarted at least once a day - in > this case the service stops without errors. But the registry still gets > corrupted. So the corruption occurs independently of whether the service > is > running or not. > There is no other application which is using MAPI so after the service > terminates, the resources (also the possible leaked ones) should be > released, > right? > I have at least 5 years of experience with MAPI programming, but this is > something which makes me crazy. No matter how you fine tune your > applications, guard them by external applications, it gets stuck and the > whole system must be restarted. If there whould be a workaround or > possibility to delete the corrupted registry key - i would be happy. > > "Dmitry Streblechenko" wrote: > >> Is your code executed on the saee thread? If yes, why do you need to call >> MAPIInitialize multiple times? >> Did you monitor the number of handles and memory usage of the process? >> Sounds llike you have a reference leak somewhere in you code... >> >> Dmitry Streblechenko (MVP) >> http://www.dimastr.com/ >> OutlookSpy - Outlook, CDO >> and MAPI Developer Tool > I can tell you that you aren't going to want to create 10000 profiles on the
system as you will get to a point where the mapi subsystem will fail. As a suggestion I would also set the profile to deferred delete and not delete them right away as this is going to access that registry key when you call Delete Profile. As with any multi-thread program you can run in to areas where one thread might be releasing some resources that are needed by another. Are you using debug asserts in your debug build to try and track this down? Are you sure that one of your other threads is not disposing its objects and calling mapi uninitialize on you? I would insert some code around the areas that are creating and deleting the profiles and print out an failed hresults, as well as you might want to use some critical sections if you are not already. There is no problem when you call MAPIInitialize on the main thread or when you shut it down, this should be like this. You might want to take a look at this as well to see if this helps: http://support.microsoft.com/kb/891425. MAPI stores "instance data" for each security context that calls MAPIInitialize. The information includes the heap handles, shared sections for interacting with other processes using the same security context, etc. Instance data lives in a structure that is keyed to a hash of the current security context's SID. So, if you create a MAPI object under one security context and release it under another, MAPI either a) fails to find the instance data and crashes, or b) frees the object from the wrong heap and corrupts the heap. How this instance data is affected by impersonation was also involved in the Deleted Profile issue. For more information on the Deleted Profile issue see this blog: http://blogs.msdn.com/stephen_griffin/archive/2004/08/20/217919.aspx. -- Show quoteThis posting is provided "AS IS" with no warranties, and confers no rights. Dgoldman http://blogs.msdn.com/dgoldman Download OABInteg from here: http://gotdotnet.com/Community/UserSamples/Download.aspx?SampleGuid=A2338E73-F521-4071-9B1D-AAF49C346ACD "Dmitry Streblechenko" <dmi***@dimastr.com> wrote in message news:eS%23krj0dHHA.596@TK2MSFTNGP06.phx.gbl... > Is your code executed on the saee thread? If yes, why do you need to call > MAPIInitialize multiple times? > Did you monitor the number of handles and memory usage of the process? > Sounds llike you have a reference leak somewhere in you code... > > Dmitry Streblechenko (MVP) > http://www.dimastr.com/ > OutlookSpy - Outlook, CDO > and MAPI Developer Tool > > "Vladimir Werskov" <Vladimir Wers***@discussions.microsoft.com> wrote in > message news:A5189D9E-2533-4839-ACF7-0C334A27D5E6@microsoft.com... >> Hello to all. >> >> We are facing a very strange problem with Extended MAPI. We have a multi >> threaded Windows service (ATL). The service is able to connect to all >> mailboxes in the organization. For this a new MAPI profile is created >> (permanent) with a unique name. The profile is used to connect to the >> mailbox, do the action on the mailbox and then logoff is called. The MAPI >> profile is immediately deleted after the logoff. >> >> This is working correctly, however after some time (weekly or monthly) >> strange thing happens: the service is not able to log on to any mailbox >> and >> the registry key (the service runs under a specific account) >> >> HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging >> Subsystem\Profiles >> >> can't be opened anymore. It is not possible to open or delete the >> registry >> key. I have searched for an open handle among the running processes for >> this >> registry key, but there was none. The registry key can only be deleted >> after >> a reboot. >> After the reboot the same situation can be reproduced at least once a >> month. >> I must add that the number of profiles created/deleted per day can exceed >> the >> number 100000. >> When the registry key gets corrupted, it is not possible to call >> MAPIInitialize - it returns MAPI_E_NOT_INITIALIZED. >> The MAPI32.dll is the one from the Exchange System Manager. No Outlook is >> installed. >> >> Is there any known issue with this registry key? >> Is there a way to restart the MAPI subsystem without restarting the >> server? >> >> Thank you very much. >> > > Thank you for your useful suggestions!
I will definitely try the MAPI_TEMPORARY_PROFILES flag. I do not want to steal your time anymore, so only for completeness: - there are no 10000 simultaneously created profiles on the system. The profile is created, logged on to. Then i perform the necessary MAPI function. After this has finished, the session is logged off and the profile is deleted. So the number of simultaneously created profiles depends on the number of request on the service. Once the task is finished, everything is cleaned up. - what do you mean by "deferred delete"? I do not remove the profile immediately - only after it is logged off - to the multi threading issues: the client of the service is always creating a new thread. This thread then creates a COM object from the service. Each COM object is generating a unique profile name. Each COM object has it's own resources. The same object is never used by another thread - only the creator. I am tracking each object and each call - printing out using OutputDebugString the THREADID and the object's 'this' address. This was fine. - i am using critical sections in profile creating and deletion. Do you suggest that i should lock the MAPIInitialize/MAPIUninitialize too? What i will try is this: - monitor the MAPIInitialize/MAPIUninitialize for each request/thread - log the result code from DeleteProfile if not S_OK What is still open is how it is possible that after the service has terminated, the registry key is not accessible. Should the OS not free up the resources after the process terminates? Show quote "Dave Goldman [MSFT]" wrote: > I can tell you that you aren't going to want to create 10000 profiles on the > system as you will get to a point where the mapi subsystem will fail. As a > suggestion I would also set the profile to deferred delete and not delete > them right away as this is going to access that registry key when you call > Delete Profile. As with any multi-thread program you can run in to areas > where one thread might be releasing some resources that are needed by > another. Are you using debug asserts in your debug build to try and track > this down? > > Are you sure that one of your other threads is not disposing its objects and > calling mapi uninitialize on you? I would insert some code around the areas > that are creating and deleting the profiles and print out an failed > hresults, as well as you might want to use some critical sections if you are > not already. > > There is no problem when you call MAPIInitialize on the main thread or when > you shut it down, this should be like this. You might want to take a look at > this as well to see if this helps: http://support.microsoft.com/kb/891425. > MAPI stores "instance data" for each security context that calls > MAPIInitialize. The information includes the heap handles, shared sections > for interacting with other processes using the same security context, etc. > Instance data lives in a structure that is keyed to a hash of the current > security context's SID. So, if you create a MAPI object under one security > context and release it under another, MAPI either a) fails to find the > instance data and crashes, or b) frees the object from the wrong heap and > corrupts the heap. How this instance data is affected by impersonation was > also involved in the Deleted Profile issue. For more information on the > Deleted Profile issue see this blog: > http://blogs.msdn.com/stephen_griffin/archive/2004/08/20/217919.aspx. > > -- > This posting is provided "AS IS" with no warranties, and confers no rights. > > Dgoldman > http://blogs.msdn.com/dgoldman > Download OABInteg from here: > http://gotdotnet.com/Community/UserSamples/Download.aspx?SampleGuid=A2338E73-F521-4071-9B1D-AAF49C346ACD > > It is very possible that the way the resources are being terminated are
doing something to the registry. It could also be possible that the way we are accessing the registry is not being fully released. As a suggestion you can try using regmon while you are running your progam and then right before the failure look to see who is touching the registry. You can then try to corrolate some time frame as to the last time your program touched the registry and the time of the corruption. Perhaps the application is failing somewhere or hitting an exception that is being eaten and not handled properly, thus you never get to see it. How many simultaneously profiles are created at the same time? The IProfAdmin::DeleteProfile method deletes a profile. If the profile to delete is in use when DeleteProfile is called, DeleteProfile returns S_OK but does *not* delete the profile immediately. Instead, DeleteProfile marks the profile for deletion and deletes it after it is no longer being used, when all of its active sessions have ended. I would put critical sections around the Initalize and UnInitialize just to make sure that its not being called by another thread. -- Show quoteThis posting is provided "AS IS" with no warranties, and confers no rights. Dgoldman http://blogs.msdn.com/dgoldman Download OABInteg from here: http://gotdotnet.com/Community/UserSamples/Download.aspx?SampleGuid=A2338E73-F521-4071-9B1D-AAF49C346ACD "Vladimir Werskov" <VladimirWers***@discussions.microsoft.com> wrote in message news:1E4CF5C2-A4CE-4767-A6D7-03036EC6627B@microsoft.com... > Thank you for your useful suggestions! > > I will definitely try the MAPI_TEMPORARY_PROFILES flag. > > I do not want to steal your time anymore, so only for completeness: > - there are no 10000 simultaneously created profiles on the system. The > profile is created, logged on to. > Then i perform the necessary MAPI function. After this has finished, the > session is logged off and the profile is deleted. > So the number of simultaneously created profiles depends on the number of > request on the service. Once the task is finished, > everything is cleaned up. > - what do you mean by "deferred delete"? I do not remove the profile > immediately - only after it is logged off > - to the multi threading issues: the client of the service is always > creating a new thread. This thread then creates a COM object > from the service. Each COM object is generating a unique profile name. > Each > COM object has it's own resources. The same object is never > used by another thread - only the creator. I am tracking each object and > each call - printing out using OutputDebugString the THREADID > and the object's 'this' address. This was fine. > - i am using critical sections in profile creating and deletion. Do you > suggest that i should lock the MAPIInitialize/MAPIUninitialize too? > > What i will try is this: > - monitor the MAPIInitialize/MAPIUninitialize for each request/thread > - log the result code from DeleteProfile if not S_OK > > What is still open is how it is possible that after the service has > terminated, the registry key is not accessible. > Should the OS not free up the resources after the process terminates? > > "Dave Goldman [MSFT]" wrote: > >> I can tell you that you aren't going to want to create 10000 profiles on >> the >> system as you will get to a point where the mapi subsystem will fail. As >> a >> suggestion I would also set the profile to deferred delete and not delete >> them right away as this is going to access that registry key when you >> call >> Delete Profile. As with any multi-thread program you can run in to areas >> where one thread might be releasing some resources that are needed by >> another. Are you using debug asserts in your debug build to try and track >> this down? >> >> Are you sure that one of your other threads is not disposing its objects >> and >> calling mapi uninitialize on you? I would insert some code around the >> areas >> that are creating and deleting the profiles and print out an failed >> hresults, as well as you might want to use some critical sections if you >> are >> not already. >> >> There is no problem when you call MAPIInitialize on the main thread or >> when >> you shut it down, this should be like this. You might want to take a look >> at >> this as well to see if this helps: >> http://support.microsoft.com/kb/891425. >> MAPI stores "instance data" for each security context that calls >> MAPIInitialize. The information includes the heap handles, shared >> sections >> for interacting with other processes using the same security context, >> etc. >> Instance data lives in a structure that is keyed to a hash of the current >> security context's SID. So, if you create a MAPI object under one >> security >> context and release it under another, MAPI either a) fails to find the >> instance data and crashes, or b) frees the object from the wrong heap and >> corrupts the heap. How this instance data is affected by impersonation >> was >> also involved in the Deleted Profile issue. For more information on the >> Deleted Profile issue see this blog: >> http://blogs.msdn.com/stephen_griffin/archive/2004/08/20/217919.aspx. >> >> -- >> This posting is provided "AS IS" with no warranties, and confers no >> rights. >> >> Dgoldman >> http://blogs.msdn.com/dgoldman >> Download OABInteg from here: >> http://gotdotnet.com/Community/UserSamples/Download.aspx?SampleGuid=A2338E73-F521-4071-9B1D-AAF49C346ACD >> >> > |
|||||||||||||||||||||||