1 //===-- MIDriverMgr.cpp -----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 // File: MIDriverMgr.cpp
13 // Overview: CMIDriverMgr implementation.
15 // Environment: Compilers: Visual C++ 12.
16 // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
17 // Libraries: See MIReadmetxt.
22 // Third Party Headers:
23 #include <lldb/API/SBError.h>
26 #include "MIDriverMgr.h"
27 #include "MICmnResources.h"
29 #include "MICmnLogMediumFile.h"
31 #include "MIUtilTermios.h"
32 #include "MICmnStreamStdout.h"
33 #include "MIUtilSingletonHelper.h"
35 //++ ------------------------------------------------------------------------------------
36 // Details: CMIDriverMgr constructor.
42 CMIDriverMgr::CMIDriverMgr(void)
43 : m_pDriverCurrent(nullptr)
48 //++ ------------------------------------------------------------------------------------
49 // Details: CMIDriverMgr destructor.
55 CMIDriverMgr::~CMIDriverMgr(void)
60 //++ ------------------------------------------------------------------------------------
61 // Details: Initialize *this manager.
64 // Return: MIstatus::success - Functional succeeded.
65 // MIstatus::failure - Functional failed.
69 CMIDriverMgr::Initialize(void)
71 m_clientUsageRefCnt++;
73 ClrErrorDescription();
76 return MIstatus::success;
78 bool bOk = MIstatus::success;
81 // Note initialisation order is important here as some resources depend on previous
82 MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg);
83 MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg);
87 MIUtilTermios::StdinTermiosSet();
94 CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_DRIVERMGR), errMsg.c_str()));
95 SetErrorDescription(strInitError);
96 return MIstatus::failure;
102 //++ ------------------------------------------------------------------------------------
103 // Details: Unbind detach or release resources used by this server in general common
104 // functionality shared between versions of any server interfaces implemented.
106 // Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!).
107 // Return: MIstatus::success - Functional succeeded.
108 // MIstatus::failure - Functional failed.
112 CMIDriverMgr::Shutdown(void)
114 // Do not want a ref counter because this function needs to be called how ever this
115 // application stops running
116 // if( --m_clientUsageRefCnt > 0 )
117 // return MIstatus::success;
119 bool vbAppExitOk = true;
121 ClrErrorDescription();
124 return MIstatus::success;
128 // The MI Driver's log updating may have been switched off switch back on to say all is ok.
129 CMICmnLog::Instance().SetEnabled(true);
131 CMICmnStreamStdout::Instance().Write(MIRSRC(IDE_MI_APP_EXIT_OK)); // Both stdout and Log
133 CMICmnLog::WriteLog(MIRSRC(IDE_MI_APP_EXIT_OK)); // Just to the Log
138 CMICmnLog &rAppLog = CMICmnLog::Instance();
139 if (rAppLog.GetEnabled())
141 const CMIUtilString msg(
142 CMIUtilString::Format(MIRSRC(IDE_MI_APP_EXIT_WITH_PROBLEM), CMICmnLogMediumFile::Instance().GetFileName().c_str()));
143 CMICmnStreamStdout::Instance().Write(msg);
147 // The MI Driver's log updating may have been switched off switch back on to say there has been problem.
148 rAppLog.SetEnabled(true);
149 const CMIUtilString msg(
150 CMIUtilString::Format(MIRSRC(IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG), CMICmnLogMediumFile::Instance().GetFileName().c_str()));
151 CMICmnStreamStdout::Instance().Write(msg);
155 m_bInitialized = false;
157 bool bOk = MIstatus::success;
158 CMIUtilString errMsg;
161 UnregisterDriverAll();
162 MIUtilTermios::StdinTermiosReset();
164 // Note shutdown order is important here
165 MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg);
166 MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg);
170 SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_DRIVERMGR), errMsg.c_str());
175 //++ ------------------------------------------------------------------------------------
176 // Details: Unregister all the Driver registered with *this manager. The manager also
180 // Return: MIstatus::success - Functional succeeded.
181 // MIstatus::failure - Functional failed.
185 CMIDriverMgr::UnregisterDriverAll(void)
187 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
188 while (it != m_mapDriverIdToDriver.end())
190 IDriver *pDriver = (*it).second;
191 pDriver->DoShutdown();
197 m_mapDriverIdToDriver.clear();
198 m_pDriverCurrent = NULL;
200 return MIstatus::success;
203 //++ ------------------------------------------------------------------------------------
204 // Details: Register a driver with *this Driver Manager. Call SetUseThisDriverToDoWork()
205 // inform the manager which driver is the one to the work. The manager calls
206 // the driver's init function which must be successful in order to complete the
209 // Args: vrDriver - (R) The driver to register.
210 // vrDriverID - (R) The driver's ID to lookup by.
211 // Return: MIstatus::success - Functional succeeded.
212 // MIstatus::failure - Functional failed.
216 CMIDriverMgr::RegisterDriver(const IDriver &vrDriver, const CMIUtilString &vrDriverID)
218 if (HaveDriverAlready(vrDriver))
219 return MIstatus::success;
221 IDriver *pDriver = const_cast<IDriver *>(&vrDriver);
222 if (!pDriver->SetId(vrDriverID))
223 return MIstatus::failure;
224 if (!pDriver->DoInitialize())
226 SetErrorDescriptionn(MIRSRC(IDS_DRIVERMGR_DRIVER_ERR_INIT), pDriver->GetName().c_str(), vrDriverID.c_str(),
227 pDriver->GetError().c_str());
228 return MIstatus::failure;
231 MapPairDriverIdToDriver_t pr(vrDriverID, pDriver);
232 m_mapDriverIdToDriver.insert(pr);
234 return MIstatus::success;
237 //++ ------------------------------------------------------------------------------------
238 // Details: Query the Driver Manager to see if *this manager has the driver already
241 // Args: vrDriver - (R) The driver to query.
242 // Return: True - registered.
243 // False - not registered.
247 CMIDriverMgr::HaveDriverAlready(const IDriver &vrDriver) const
249 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
250 while (it != m_mapDriverIdToDriver.end())
252 const IDriver *pDrvr = (*it).second;
253 if (pDrvr == &vrDriver)
263 //++ ------------------------------------------------------------------------------------
264 // Details: Unregister a driver from the Driver Manager. Call the SetUseThisDriverToDoWork()
265 // function to define another driver to do work if the one being unregistered did
266 // the work previously.
268 // Args: vrDriver - (R) The driver to unregister.
269 // Return: MIstatus::success - Functional succeeded.
270 // MIstatus::failure - Functional failed.
274 CMIDriverMgr::UnregisterDriver(const IDriver &vrDriver)
276 const IDriver *pDrvr = nullptr;
277 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
278 while (it != m_mapDriverIdToDriver.end())
280 pDrvr = (*it).second;
281 if (pDrvr == &vrDriver)
287 m_mapDriverIdToDriver.erase(it);
289 if (m_pDriverCurrent == pDrvr)
290 m_pDriverCurrent = nullptr;
292 return MIstatus::success;
295 //++ ------------------------------------------------------------------------------------
296 // Details: Specify the driver to do work. The Driver Manager drives this driver. Any
297 // previous driver doing work is not called anymore (so be sure the previous
298 // driver is in a tidy state before stopping it working).
300 // Args: vrADriver - (R) A lldb::SBBroadcaster/IDriver derived object.
301 // Return: MIstatus::success - Functional succeeded.
302 // MIstatus::failure - Functional failed.
306 CMIDriverMgr::SetUseThisDriverToDoWork(const IDriver &vrADriver)
308 m_pDriverCurrent = const_cast<IDriver *>(&vrADriver);
310 const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_SAY_DRIVER_USING), m_pDriverCurrent->GetName().c_str()));
311 m_pLog->Write(msg, CMICmnLog::eLogVerbosity_Log);
313 m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver();
315 return MIstatus::success;
318 //++ ------------------------------------------------------------------------------------
319 // Details: Ask *this manager which driver is currently doing the work.
322 // Return: IDriver * - Pointer to a driver, NULL if there is no current working driver.
325 CMIDriverMgr::IDriver *
326 CMIDriverMgr::GetUseThisDriverToDoWork(void) const
328 return m_pDriverCurrent;
331 //++ ------------------------------------------------------------------------------------
332 // Details: Call this function puts *this driver to work.
335 // Return: MIstatus::success - Functional succeeded.
336 // MIstatus::failure - Functional failed.
340 CMIDriverMgr::DriverMainLoop(void)
342 if (m_pDriverCurrent != nullptr)
344 if (!m_pDriverCurrent->DoMainLoop())
346 const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_MAINLOOP), m_pDriverCurrent->GetError().c_str()));
347 CMICmnStreamStdout::Instance().Write(errMsg, true);
348 return MIstatus::failure;
353 const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
354 CMICmnStreamStdout::Instance().Write(errMsg, true);
355 return MIstatus::failure;
358 return MIstatus::success;
361 //++ ------------------------------------------------------------------------------------
362 // Details: Call *this driver to resize the console window.
364 // Args: vWindowSizeWsCol - (R) New window column size.
365 // Return: MIstatus::success - Functional succeeded.
366 // MIstatus::failure - Functional failed.
370 CMIDriverMgr::DriverResizeWindow(const uint32_t vWindowSizeWsCol)
372 if (m_pDriverCurrent != nullptr)
373 return m_pDriverCurrent->DoResizeWindow(vWindowSizeWsCol);
376 const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
377 CMICmnStreamStdout::Instance().Write(errMsg, true);
381 //++ ------------------------------------------------------------------------------------
382 // Details: Get the current driver to validate executable command line arguments.
384 // Args: argc - (R) An integer that contains the count of arguments that follow in
385 // argv. The argc parameter is always greater than or equal to 1.
386 // argv - (R) An array of null-terminated strings representing command-line
387 // arguments entered by the user of the program. By convention,
388 // argv[0] is the command with which the program is invoked.
389 // vpStdOut - (R) Point to a standard output stream.
390 // vwbExiting - (W) True = *this want to exit, false = continue to work.
391 // Return: MIstatus::success - Functional succeeded.
392 // MIstatus::failure - Functional failed.
396 CMIDriverMgr::DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting)
398 if (m_pDriverCurrent == nullptr)
400 const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
401 CMICmnStreamStdout::Instance().Write(errMsg, true);
402 return MIstatus::failure;
405 const lldb::SBError error(m_pDriverCurrent->DoParseArgs(argc, argv, vpStdOut, vwbExiting));
406 bool bOk = !error.Fail();
409 CMIUtilString errMsg;
410 const MIchar *pErrorCstr = error.GetCString();
411 if (pErrorCstr != nullptr)
412 errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS), m_pDriverCurrent->GetName().c_str(), pErrorCstr);
414 errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN), m_pDriverCurrent->GetName().c_str());
416 bOk = CMICmnStreamStdout::Instance().Write(errMsg, true);
422 //++ ------------------------------------------------------------------------------------
423 // Details: Retrieve the current driver's last error condition.
426 // Return: CMIUtilString - Text description.
430 CMIDriverMgr::DriverGetError(void) const
432 if (m_pDriverCurrent != nullptr)
433 return m_pDriverCurrent->GetError();
436 const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
437 CMICmnStreamStdout::Instance().Write(errMsg, true);
440 return CMIUtilString();
443 //++ ------------------------------------------------------------------------------------
444 // Details: Retrieve the current driver's name.
447 // Return: CMIUtilString - Driver name.
448 // Empty string = no current working driver specified.
452 CMIDriverMgr::DriverGetName(void) const
454 if (m_pDriverCurrent != nullptr)
455 return m_pDriverCurrent->GetName();
458 const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
459 CMICmnStreamStdout::Instance().Write(errMsg, true);
462 return CMIUtilString();
465 //++ ------------------------------------------------------------------------------------
466 // Details: Retrieve the current driver's debugger object.
469 // Return: lldb::SBDebugger * - Ptr to driver's debugger object.
470 // - NULL = no current working driver specified.
474 CMIDriverMgr::DriverGetTheDebugger(void)
476 lldb::SBDebugger *pDebugger = nullptr;
477 if (m_pDriverCurrent != nullptr)
478 pDebugger = &m_pDriverCurrent->GetTheDebugger();
481 const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
482 CMICmnStreamStdout::Instance().Write(errMsg, true);
488 //++ ------------------------------------------------------------------------------------
489 // Details: Check the arguments given on the command line. The main purpose of this
490 // function is to check for the presence of the --interpreter option. Having
491 // this option present tells *this manager to set the CMIDriver to do work. If
492 // not use the LLDB driver. The following are options that are only handled by
493 // the CMIDriverMgr are:
500 // The above arguments are not handled by any driver object except for --executable.
501 // The options --interpreter and --executable in code act very similar. The
502 // --executable is necessary to differentiate whither the MI Driver is being using
503 // by a client i.e. Eclipse or from the command line. Eclipse issues the option
504 // --interpreter and also passes additional arguments which can be interpreted as an
505 // executable if called from the command line. Using --executable tells the MI
506 // Driver is being called the command line and that the executable argument is indeed
507 // a specified executable an so actions commands to set up the executable for a
508 // debug session. Using --interpreter on the commnd line does not action additional
509 // commands to initialise a debug session and so be able to launch the process.
511 // Args: argc - (R) An integer that contains the count of arguments that follow in
512 // argv. The argc parameter is always greater than or equal to 1.
513 // argv - (R) An array of null-terminated strings representing command-line
514 // arguments entered by the user of the program. By convention,
515 // argv[0] is the command with which the program is invoked.
516 // vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s),
517 // version information only.
518 // False = Continue to work, start debugger i.e. Command
520 // Return: lldb::SBError - LLDB current error status.
524 CMIDriverMgr::ParseArgs(const int argc, const char *argv[], bool &vwbExiting)
526 bool bOk = MIstatus::success;
530 // Print MI application path to the Log file
531 const CMIUtilString appPath(CMIUtilString::Format(MIRSRC(IDS_MI_APP_FILEPATHNAME), argv[0]));
532 bOk = m_pLog->Write(appPath, CMICmnLog::eLogVerbosity_Log);
534 // Print application arguments to the Log file
535 const bool bHaveArgs(argc >= 2);
536 CMIUtilString strArgs(MIRSRC(IDS_MI_APP_ARGS));
539 strArgs += MIRSRC(IDS_WORD_NONE);
540 bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log);
544 for (MIint i = 1; i < argc; i++)
546 strArgs += CMIUtilString::Format("%d:'%s' ", i, argv[i]);
548 bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log);
551 // Look for the command line options
552 bool bHaveArgInterpret = false;
553 bool bHaveArgVersion = false;
554 bool bHaveArgVersionLong = false;
555 bool bHaveArgNoLog = false;
556 bool bHaveArgHelp = false;
558 // Hardcode the use of the MI driver
559 #if MICONFIG_DEFAULT_TO_MI_DRIVER
560 bHaveArgInterpret = true;
561 #endif // MICONFIG_DEFAULT_TO_MI_DRIVER
565 // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING
566 for (MIint i = 1; i < argc; i++)
568 // *** Add args to help in GetHelpOnCmdLineArgOptions() ***
569 const CMIUtilString strArg(argv[i]);
571 // Argument "--executable" is also check for in CMIDriver::ParseArgs()
572 if ((0 == strArg.compare("--interpreter")) || // Given by the client such as Eclipse
573 (0 == strArg.compare("--executable"))) // Used to specify that there is executable argument also on the command line
574 { // See fn description.
575 bHaveArgInterpret = true;
577 if (0 == strArg.compare("--version"))
579 bHaveArgVersion = true;
581 if (0 == strArg.compare("--versionLong"))
583 bHaveArgVersionLong = true;
585 if (0 == strArg.compare("--noLog"))
587 bHaveArgNoLog = true;
589 if ((0 == strArg.compare("--help")) || (0 == strArg.compare("-h")))
598 CMICmnLog::Instance().SetEnabled(false);
601 // Todo: Remove this output when MI is finished. It is temporary to persuade Ecllipse plugin to work.
602 // Eclipse reads this literally and will not work unless it gets this exact version text.
603 // Handle --version option (ignore the --interpreter option if present)
607 bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(MIRSRC(IDE_MI_VERSION_GDB));
611 // Todo: Make this the --version when the the above --version version is removed
612 // Handle --versionlong option (ignore the --interpreter option if present)
613 if (bHaveArgVersionLong)
616 bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetAppVersion());
620 // Both '--help' and '--intepreter' means give help for MI only. Without
621 // '--interpreter' help the LLDB driver is working and so help is for that.
622 if (bHaveArgHelp && bHaveArgInterpret)
625 bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetHelpOnCmdLineArgOptions());
629 // This makes the assumption that there is at least one MI compatible
630 // driver registered and one LLDB driver registerd and the CMIDriver
631 // is the first one found.
632 // ToDo: Implement a better solution that handle any order, any number
633 // of drivers. Or this 'feature' may be removed if deemed not required.
634 IDriver *pLldbDriver = GetFirstNonMIDriver();
635 IDriver *pMi2Driver = GetFirstMIDriver();
636 if (bHaveArgInterpret && (pMi2Driver != nullptr))
637 bOk = bOk && SetUseThisDriverToDoWork(*pMi2Driver);
638 else if (pLldbDriver != nullptr)
639 bOk = bOk && SetUseThisDriverToDoWork(*pLldbDriver);
645 const CMIUtilString msg(MIRSRC(IDS_DRIVER_ERR_NON_REGISTERED));
646 bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(msg);
653 //++ ------------------------------------------------------------------------------------
654 // Details: Return formatted application version and name information.
657 // Return: CMIUtilString - Text data.
661 CMIDriverMgr::GetAppVersion(void) const
663 const CMIUtilString strProj(MIRSRC(IDS_PROJNAME));
664 const CMIUtilString strVsn(CMIDriver::Instance().GetVersionDescription());
665 const CMIUtilString strGdb(MIRSRC(IDE_MI_VERSION_GDB));
666 const CMIUtilString strVrsnInfo(CMIUtilString::Format("%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str()));
671 //++ ------------------------------------------------------------------------------------
672 // Details: Return formatted help information on all the MI command line options.
675 // Return: CMIUtilString - Text data.
679 CMIDriverMgr::GetHelpOnCmdLineArgOptions(void) const
681 const CMIUtilString pHelp[] = {
682 MIRSRC(IDE_MI_APP_DESCRIPTION),
683 MIRSRC(IDE_MI_APP_INFORMATION),
684 MIRSRC(IDE_MI_APP_ARG_USAGE),
685 MIRSRC(IDE_MI_APP_ARG_HELP),
686 MIRSRC(IDE_MI_APP_ARG_VERSION),
687 MIRSRC(IDE_MI_APP_ARG_VERSION_LONG),
688 MIRSRC(IDE_MI_APP_ARG_INTERPRETER),
689 MIRSRC(IDE_MI_APP_ARG_EXECUTEABLE),
690 CMIUtilString::Format(MIRSRC(IDE_MI_APP_ARG_NO_APP_LOG), CMICmnLogMediumFile::Instance().GetFileName().c_str()),
691 MIRSRC(IDE_MI_APP_ARG_EXECUTABLE),
692 MIRSRC(IDS_CMD_QUIT_HELP),
693 MIRSRC(IDE_MI_APP_ARG_EXAMPLE)};
694 const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[0];
695 CMIUtilString strHelp;
696 for (MIuint i = 0; i < nHelpItems; i++)
705 //++ ------------------------------------------------------------------------------------
706 // Details: Search the registered drivers and return the first driver which says it is
707 // GDB/MI compatible i.e. the CMIDriver class.
710 // Return: IDriver * - Ptr to driver, NULL = no driver found.
713 CMIDriverMgr::IDriver *
714 CMIDriverMgr::GetFirstMIDriver(void) const
716 IDriver *pDriver = nullptr;
717 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
718 while (it != m_mapDriverIdToDriver.end())
720 const CMIUtilString &rDrvId = (*it).first;
722 IDriver *pDvr = (*it).second;
723 if (pDvr->GetDriverIsGDBMICompatibleDriver())
736 //++ ------------------------------------------------------------------------------------
737 // Details: Search the registered drivers and return the first driver which says it is
738 // not GDB/MI compatible i.e. the LLDB Driver class.
741 // Return: IDriver * - Ptr to driver, NULL = no driver found.
744 CMIDriverMgr::IDriver *
745 CMIDriverMgr::GetFirstNonMIDriver(void) const
747 IDriver *pDriver = nullptr;
748 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
749 while (it != m_mapDriverIdToDriver.end())
751 const CMIUtilString &rDrvId = (*it).first;
753 IDriver *pDvr = (*it).second;
754 if (!pDvr->GetDriverIsGDBMICompatibleDriver())
767 //++ ------------------------------------------------------------------------------------
768 // Details: Search the registered drivers and return driver with the specified ID.
770 // Args: vrDriverId - (R) ID of a driver.
771 // Return: IDriver * - Ptr to driver, NULL = no driver found.
774 CMIDriverMgr::IDriver *
775 CMIDriverMgr::GetDriver(const CMIUtilString &vrDriverId) const
777 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.find(vrDriverId);
778 if (it == m_mapDriverIdToDriver.end())
781 IDriver *pDriver = (*it).second;