Source code of Windows XP (NT5)
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.

349 lines
9.8 KiB

  1. #include <mvopsys.h>
  2. #ifdef _DEBUG
  3. static char s_aszModule[] = __FILE__; /* For error report */
  4. #endif
  5. #include <windows.h>
  6. #include <_mvutil.h>
  7. #include <orkin.h>
  8. #include <ITverinfo.h>
  9. #include "objmngr.h"
  10. #ifdef IA64
  11. #include <itdfguid.h>
  12. #endif
  13. CObjectInstHandler::CObjectInstHandler()
  14. {
  15. m_hMemory = NULL;
  16. m_pObjects = NULL;
  17. m_fInitNew = FALSE;
  18. m_fIsDirty = FALSE;
  19. m_iMaxItem = 0;
  20. m_iCurItem = 0;
  21. }
  22. CObjectInstHandler::~CObjectInstHandler()
  23. {
  24. (void)Close();
  25. }
  26. STDMETHODIMP CObjectInstHandler::InitNew()
  27. {
  28. if(TRUE == m_fInitNew)
  29. return SetErrReturn(E_UNEXPECTED);
  30. m_fIsDirty = TRUE; // Set to false after breakers work
  31. HRESULT hr = S_OK;
  32. if(NULL == (m_hMemory = _GLOBALALLOC
  33. (DLLGMEM_ZEROINIT, OBJINST_BASE * sizeof(OBJINSTMEMREC))))
  34. SetErrCode (&hr, E_OUTOFMEMORY);
  35. if(SUCCEEDED(hr))
  36. {
  37. m_pObjects = (POBJINSTMEMREC)_GLOBALLOCK(m_hMemory);
  38. ITASSERT(m_pObjects);
  39. m_iCurItem = 0;
  40. m_iMaxItem = OBJINST_BASE;
  41. }
  42. return hr;
  43. } /* InitNew */
  44. STDMETHODIMP CObjectInstHandler::Close()
  45. {
  46. if(!m_hMemory)
  47. return S_OK;
  48. POBJINSTMEMREC pObjArray = m_pObjects;
  49. for (DWORD loop = 0; loop < m_iCurItem; loop++, pObjArray++)
  50. pObjArray->pUnknown->Release();
  51. _GLOBALUNLOCK(m_hMemory);
  52. _GLOBALFREE(m_hMemory);
  53. m_iMaxItem = 0;
  54. m_iCurItem = 0;
  55. m_pObjects = NULL;
  56. m_hMemory = NULL;
  57. m_fInitNew = FALSE;
  58. m_fIsDirty = FALSE;
  59. return S_OK;
  60. } /* Close */
  61. STDMETHODIMP CObjectInstHandler::AddObject(REFCLSID clsid, DWORD *pdwObjInstance)
  62. {
  63. if (NULL == pdwObjInstance)
  64. return SetErrReturn(E_INVALIDARG);
  65. // Can we write the out param?
  66. if (IsBadWritePtr(pdwObjInstance, sizeof(DWORD)))
  67. {
  68. ITASSERT(0);
  69. return SetErrReturn(E_INVALIDARG);
  70. }
  71. IUnknown *pUnknown;
  72. HRESULT hr = CoCreateInstance
  73. (clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnknown);
  74. if (FAILED(hr))
  75. return hr;
  76. IPersistStreamInit *pPersist;
  77. if (SUCCEEDED(hr = pUnknown->QueryInterface
  78. (IID_IPersistStreamInit, (void **)&pPersist)))
  79. {
  80. (void)pPersist->InitNew();
  81. pPersist->Release();
  82. }
  83. if (m_iCurItem == m_iMaxItem)
  84. {
  85. HANDLE hNewMem;
  86. _GLOBALUNLOCK(m_hMemory);
  87. hNewMem = _GLOBALREALLOC (m_hMemory,
  88. (m_iMaxItem + OBJINST_INCREMENT) * sizeof(OBJINSTMEMREC), 0);
  89. if (NULL == hNewMem)
  90. {
  91. *pdwObjInstance = 0;
  92. return SetErrReturn(E_OUTOFMEMORY);
  93. }
  94. m_hMemory = hNewMem;
  95. m_pObjects = (POBJINSTMEMREC)_GLOBALLOCK(m_hMemory);
  96. m_iMaxItem += OBJINST_INCREMENT;
  97. }
  98. (m_pObjects + m_iCurItem)->pUnknown = pUnknown;
  99. (m_pObjects + m_iCurItem)->clsid = clsid;
  100. *pdwObjInstance = m_iCurItem++;
  101. m_fIsDirty = TRUE;
  102. return S_OK;
  103. } /* CObjectInstHandler::AddObject */
  104. STDMETHODIMP CObjectInstHandler::GetObject
  105. (DWORD dwObjInstance, REFIID riid, void **ppv)
  106. {
  107. if (NULL == ppv)
  108. return SetErrReturn(E_INVALIDARG);
  109. // Can we write the out param?
  110. if (IsBadWritePtr(ppv, sizeof(void *)))
  111. {
  112. ITASSERT(0);
  113. return SetErrReturn(E_INVALIDARG);
  114. }
  115. *ppv = NULL;
  116. if (dwObjInstance >= m_iCurItem)
  117. return SetErrReturn(E_NOTEXIST);
  118. IUnknown *pUnknown = (m_pObjects + dwObjInstance)->pUnknown;
  119. if (NULL == pUnknown)
  120. return SetErrReturn(E_NOTEXIST);
  121. return pUnknown->QueryInterface(riid, ppv);
  122. } /* CObjectInstHandler::GetObject */
  123. STDMETHODIMP CObjectInstHandler::Save(LPSTREAM pStream, BOOL fClearDirty)
  124. {
  125. if (NULL == pStream)
  126. return SetErrReturn(E_INVALIDARG);
  127. // Build up the header
  128. OBJ_INSTANCE_CACHE ObjInstCache;
  129. ObjInstCache.Header.dwVersion =
  130. MAKELONG(MAKEWORD(0, rapFile), MAKEWORD(rmmFile, rmjFile));
  131. ObjInstCache.Header.dwEntries = m_iCurItem;
  132. if (NULL == (ObjInstCache.hRecords = _GLOBALALLOC
  133. (GMEM_MOVEABLE, sizeof(OBJ_INSTANCE_RECORD) * m_iMaxItem)))
  134. return SetErrReturn (E_OUTOFMEMORY);
  135. ObjInstCache.pRecords =
  136. (POBJ_INSTANCE_RECORD)_GLOBALLOCK(ObjInstCache.hRecords);
  137. POBJ_INSTANCE_RECORD pRecord = ObjInstCache.pRecords;
  138. // Save stream start pointer
  139. LARGE_INTEGER liTemp = {0};
  140. ULARGE_INTEGER liStart;
  141. HRESULT hr;
  142. if (FAILED(hr = pStream->Seek(liTemp, STREAM_SEEK_CUR, &liStart)))
  143. {
  144. exit0:
  145. _GLOBALUNLOCK(ObjInstCache.hRecords);
  146. _GLOBALFREE(ObjInstCache.hRecords);
  147. return hr;
  148. }
  149. // Write dummy header to beginning of file
  150. DWORD dwOffset =
  151. sizeof(OBJ_INSTANCE_HEADER) + m_iCurItem * sizeof(OBJ_INSTANCE_RECORD);
  152. DWORD dwHeaderSize = dwOffset;
  153. if (FAILED(hr = pStream->Write(&ObjInstCache, dwHeaderSize, NULL)))
  154. goto exit0;
  155. POBJINSTMEMREC pObjArray = m_pObjects;
  156. for (DWORD loop = 0; loop < m_iCurItem; loop++, pObjArray++, pRecord++)
  157. {
  158. pRecord->dwOffset = dwOffset;
  159. // When we loaded this we coulnd't create this object. It is
  160. // essentially dead. In this state we can not save. This is not
  161. // an issue for IT40, since we never save the database at run-time
  162. if (NULL == pObjArray->pUnknown)
  163. {
  164. ITASSERT(0);
  165. SetErrCode(&hr, E_UNEXPECTED);
  166. goto exit0;
  167. }
  168. // Save current stream pointer
  169. ULARGE_INTEGER liStart; // Local scope - Don't confuse with
  170. // function scoped variable of the same name
  171. if (FAILED(hr = pStream->Seek(liTemp, STREAM_SEEK_CUR, &liStart)))
  172. goto exit0;
  173. // Write CLSID
  174. if (FAILED(hr = pStream->Write(&pObjArray->clsid, sizeof(CLSID), NULL)))
  175. goto exit0;
  176. // Get IPersistStreamInit interface and save persistance data
  177. IPersistStreamInit *pPersist;
  178. if (SUCCEEDED(hr = pObjArray->pUnknown->QueryInterface
  179. (IID_IPersistStreamInit, (void**)&pPersist)))
  180. {
  181. // Write persistance data
  182. hr = pPersist->Save(pStream, fClearDirty);
  183. pPersist->Release();
  184. if (FAILED(hr))
  185. goto exit0;
  186. }
  187. // Get current stream pointer
  188. ULARGE_INTEGER liEnd;
  189. if (FAILED(hr = pStream->Seek(liTemp, STREAM_SEEK_CUR, &liEnd)))
  190. goto exit0;
  191. pRecord->dwSize = (DWORD)(liEnd.QuadPart - liStart.QuadPart);
  192. dwOffset += pRecord->dwSize;
  193. }
  194. // Write completed header
  195. liTemp.QuadPart = liStart.QuadPart;
  196. if (FAILED(hr = pStream->Seek(liTemp, STREAM_SEEK_SET, NULL)))
  197. goto exit0;
  198. if (FAILED(hr = pStream->Write
  199. (&ObjInstCache.Header, sizeof (OBJ_INSTANCE_HEADER), NULL)))
  200. goto exit0;
  201. hr = pStream->Write(ObjInstCache.pRecords,
  202. dwHeaderSize - sizeof (OBJ_INSTANCE_HEADER), NULL);
  203. m_fIsDirty = FALSE;
  204. goto exit0;
  205. } /* CObjectInstHandler::Save */
  206. STDMETHODIMP CObjectInstHandler::Load(LPSTREAM pStream)
  207. {
  208. if (TRUE == m_fInitNew)
  209. return SetErrReturn(E_UNEXPECTED);
  210. if (NULL == pStream || IsBadReadPtr(pStream, sizeof(void *)))
  211. return SetErrReturn(E_INVALIDARG);
  212. HRESULT hr;
  213. // Read header from stream
  214. OBJ_INSTANCE_CACHE objCache;
  215. hr = pStream->Read(&objCache, sizeof(OBJ_INSTANCE_HEADER), NULL);
  216. if (FAILED(hr))
  217. return SetErrReturn(hr);
  218. if (objCache.Header.dwVersion != MAKELONG(MAKEWORD(0, rapFile), MAKEWORD(rmmFile, rmjFile)))
  219. return SetErrReturn(E_BADVERSION);
  220. m_iMaxItem = m_iCurItem = objCache.Header.dwEntries;
  221. // Allocate memory for run-time table
  222. if (NULL == (m_hMemory = _GLOBALALLOC
  223. (DLLGMEM_ZEROINIT, m_iCurItem * sizeof(OBJINSTMEMREC))))
  224. return SetErrReturn(E_OUTOFMEMORY);
  225. m_pObjects = (POBJINSTMEMREC)_GLOBALLOCK(m_hMemory);
  226. ITASSERT(m_pObjects);
  227. // Allocate memory for the stream index table
  228. if (NULL == (objCache.hRecords = _GLOBALALLOC
  229. (DLLGMEM_ZEROINIT, m_iCurItem * sizeof(OBJ_INSTANCE_RECORD))))
  230. {
  231. hr = SetErrCode(&hr, E_OUTOFMEMORY);
  232. exit0:
  233. if (FAILED(hr))
  234. {
  235. _GLOBALUNLOCK(m_hMemory);
  236. _GLOBALFREE(m_hMemory);
  237. m_hMemory = NULL;
  238. m_pObjects = NULL;
  239. }
  240. return hr;
  241. }
  242. objCache.pRecords = (POBJ_INSTANCE_RECORD)_GLOBALLOCK(objCache.hRecords);
  243. ITASSERT(objCache.pRecords);
  244. // Read in the stream index table
  245. if (FAILED(hr = pStream->Read(objCache.pRecords,
  246. m_iCurItem * sizeof(OBJ_INSTANCE_RECORD), NULL)))
  247. {
  248. exit1:
  249. _GLOBALUNLOCK(objCache.hRecords);
  250. _GLOBALFREE(objCache.hRecords);
  251. goto exit0;
  252. }
  253. // Proces each object in the table
  254. POBJINSTMEMREC pObjArray = m_pObjects;
  255. for (DWORD loop = 0; loop < m_iCurItem; loop++, pObjArray++)
  256. {
  257. LARGE_INTEGER liTemp;
  258. liTemp.QuadPart = objCache.pRecords[loop].dwOffset;
  259. if (FAILED(hr = pStream->Seek(liTemp, STREAM_SEEK_SET, NULL)))
  260. goto exit1;
  261. pStream->Read(&pObjArray->clsid, sizeof(CLSID), NULL);
  262. // Create COM Object
  263. hr = CoCreateInstance (pObjArray->clsid, NULL,
  264. CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pObjArray->pUnknown);
  265. if (SUCCEEDED(hr))
  266. {
  267. // Check for IPersistStreamInit interface
  268. IPersistStreamInit *pPersist;
  269. if (SUCCEEDED(hr = pObjArray->pUnknown->QueryInterface
  270. (IID_IPersistStreamInit, (void**)&pPersist)))
  271. {
  272. // Read persistance data
  273. if (FAILED(hr = pPersist->Load(pStream)))
  274. {
  275. pObjArray->pUnknown->Release();
  276. pObjArray->pUnknown = NULL;
  277. }
  278. pPersist->Release();
  279. }
  280. }
  281. }
  282. m_fIsDirty = FALSE;
  283. hr = S_OK;
  284. goto exit1;
  285. } /* CObjectInstHandler::Load */
  286. inline STDMETHODIMP CObjectInstHandler::IsDirty(void)
  287. {
  288. return (m_fIsDirty ? S_OK : S_FALSE);
  289. } /* IsDirty */