Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.0 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // Factory.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // This file defines the class FactoryCache.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/05/1998 Original version.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include <ias.h>
  19. #include <iasutil.h>
  20. #include <factory.h>
  21. //////////
  22. // The global factory cache.
  23. //////////
  24. FactoryCache theFactoryCache(IASProgramName);
  25. Factory::Factory(PCWSTR progID, IClassFactory* classFactory)
  26. {
  27. // Check the arguments.
  28. if (progID == NULL || classFactory == NULL)
  29. { _com_issue_error(E_POINTER); }
  30. // Copy the progID string.
  31. name = wcscpy(new WCHAR[wcslen(progID) + 1], progID);
  32. // Save the classFactory pointer. We must do this after the string
  33. // copy since the memory allocation may throw std::bad_alloc.
  34. (factory = classFactory)->AddRef();
  35. }
  36. Factory::Factory(const Factory& f)
  37. : name(wcscpy(new WCHAR[wcslen(f.name) + 1], f.name)),
  38. factory(f.factory)
  39. {
  40. factory->AddRef();
  41. }
  42. Factory& Factory::operator=(const Factory& f)
  43. {
  44. // Make sure the copy succeeds before we release our state.
  45. PWSTR newName = wcscpy(new WCHAR[wcslen(f.name) + 1], f.name);
  46. // Free up our current state.
  47. delete[] name;
  48. factory->Release();
  49. // Copy in the new state.
  50. name = newName;
  51. (factory = f.factory)->AddRef();
  52. return *this;
  53. }
  54. Factory::~Factory() throw ()
  55. {
  56. factory->Release();
  57. delete[] name;
  58. }
  59. FactoryCache::FactoryCache(PCWSTR defaultPrefix)
  60. {
  61. if (defaultPrefix)
  62. {
  63. // Allocate memory.
  64. prefixLen = wcslen(defaultPrefix) + 2;
  65. prefix = new WCHAR[prefixLen];
  66. // Copy in the prefix.
  67. wcscpy(prefix, defaultPrefix);
  68. // Add the dot delimiter.
  69. wcscat(prefix, L".");
  70. }
  71. else
  72. {
  73. prefixLen = 0;
  74. prefix = NULL;
  75. }
  76. }
  77. FactoryCache::~FactoryCache() throw ()
  78. {
  79. delete[] prefix;
  80. }
  81. void FactoryCache::clear() throw ()
  82. {
  83. _serialize
  84. factories.clear();
  85. }
  86. void FactoryCache::CLSIDFromProgID(PCWSTR progID, LPCLSID pclsid) const
  87. {
  88. if (prefix)
  89. {
  90. // Concatenate the prefix and the progID.
  91. size_t len = wcslen(progID) + prefixLen;
  92. PWSTR withPrefix = (PWSTR)_alloca(len * sizeof(WCHAR));
  93. memcpy(withPrefix, prefix, prefixLen * sizeof(WCHAR));
  94. wcscat(withPrefix, progID);
  95. // Try with the prefix prepended ...
  96. if (SUCCEEDED(::CLSIDFromProgID(withPrefix, pclsid))) { return; }
  97. }
  98. // ... then try it exactly as passed in.
  99. _com_util::CheckError(::CLSIDFromProgID(progID, pclsid));
  100. }
  101. void FactoryCache::createInstance(PCWSTR progID,
  102. IUnknown* pUnkOuter,
  103. REFIID riid,
  104. void** ppvObject)
  105. {
  106. // This is *very* hokey, but it beats creating a real Factory object.
  107. Factory& key = *(Factory*)(&progID);
  108. _serialize
  109. // Check our cache for the progID.
  110. std::set<Factory>::iterator factory = factories.find(key);
  111. if (factory == factories.end())
  112. {
  113. // Look up the CLSID for this progID.
  114. CLSID clsid;
  115. CLSIDFromProgID(progID, &clsid);
  116. // Retrieve the Class Factory.
  117. CComPtr<IClassFactory> newFactory;
  118. _com_util::CheckError(CoGetClassObject(clsid,
  119. CLSCTX_INPROC_SERVER,
  120. NULL,
  121. __uuidof(IClassFactory),
  122. (PVOID*)&newFactory));
  123. // Insert it into the cache.
  124. factories.insert(Factory(progID, newFactory));
  125. // Retrieve the newly created master.
  126. factory = factories.find(key);
  127. }
  128. // Create the requested object.
  129. factory->createInstance(pUnkOuter, riid, ppvObject);
  130. }