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.

401 lines
11 KiB

  1. /*******************************************************
  2. * @doc SHROOM EXTERNAL API *
  3. * *
  4. * DBIMP.CPP *
  5. * *
  6. * Copyright (C) Microsoft Corporation 1997 *
  7. * All rights reserved. *
  8. * *
  9. * This file contains the local *
  10. * implementation of CDatabase. *
  11. * *
  12. ********************************************************
  13. * *
  14. * Header section added by Anita Legsdin so that *
  15. * comments will appear in Autodoc *
  16. * *
  17. *******************************************************/
  18. // DBIMP.CPP: Implementation of CDatabase
  19. // I'd like to get rid of this, but for now we include it so this compiles
  20. #ifdef _DEBUG
  21. static char s_aszModule[] = __FILE__; /* For error report */
  22. #endif
  23. #include <atlinc.h>
  24. // MediaView (InfoTech) includes
  25. #include <mvopsys.h>
  26. #include <groups.h>
  27. #include <wwheel.h>
  28. #include <msitstg.h>
  29. #include <ccfiles.h>
  30. #include "itdb.h"
  31. #include "DBImp.h"
  32. // TODO TODO TODO: Replace the blind use of critical sections with a
  33. // better way of ensuring thread-safeness while preserving performance.
  34. // But for now, in the interest of coding time, we just make sure the
  35. // code is thread-safe.
  36. //---------------------------------------------------------------------------
  37. // Constructor and Destructor
  38. //---------------------------------------------------------------------------
  39. CITDatabaseLocal::CITDatabaseLocal()
  40. {
  41. m_pStorage = NULL;
  42. }
  43. CITDatabaseLocal::~CITDatabaseLocal()
  44. {
  45. Close();
  46. }
  47. //---------------------------------------------------------------------------
  48. // IITDatabase Method Implemenations
  49. //---------------------------------------------------------------------------
  50. /********************************************************************
  51. * @method STDMETHODIMP | IITDatabase | Open |
  52. * Opens a database
  53. *
  54. * @parm LPCWSTR | lpszHost | Host name. You can pass NULL if calling Open
  55. * locally, otherwise this string should contain the host description string, described
  56. * below.
  57. *
  58. * @parm LPCWSTR | lpszMoniker | Name of database file to open. This should include
  59. * the full path to the file name, if calling locally. If calling using HTTP, this
  60. * should contain the ISAPI extension DLL name followed by the relative path to the database
  61. * file, for example:
  62. *
  63. * isapiext.dll?path1\path2\db.its
  64. *
  65. * @parm DWORD | dwFlags | Currently not used
  66. *
  67. * @rvalue STG_E* | Any of the IStorage errors that can occur when opening a storage.
  68. * @rvalue S_OK | The database was successfully opened
  69. *
  70. * @comm Current implementation opens all databases using the IT storage system (ITSS).
  71. * As a consequence, all databases must be built using ITSS.
  72. *
  73. * Currently two transport protocols are supported: local in-proc and HTTP. For the
  74. * local protocol the host name is NULL. For HTTP, it must be set to the transport address
  75. * of the machine which is running the ITIR ISAPI extension. For example, one possible HTTP
  76. * host name string would be "http:\\www.microsoft.com\"
  77. *
  78. * This method might attempt to connect to the database in order to load configuration information.
  79. ********************************************************************/
  80. STDMETHODIMP CITDatabaseLocal::Open(LPCWSTR lpszHost, LPCWSTR lpszMoniker, DWORD dwFlags)
  81. {
  82. HRESULT hr;
  83. IITStorage* pITStorage = NULL;
  84. if (NULL == lpszMoniker)
  85. return SetErrReturn(E_INVALIDARG);
  86. // For now, we assume we're getting an ITSS file
  87. // We might want to replace this later with more sophisticated code
  88. // that parses the given moniker
  89. m_cs.Lock();
  90. if (m_pStorage)
  91. return SetErrReturn(E_ALREADYINIT);
  92. // Open storage READ-only; we only need one instance
  93. if (SUCCEEDED(hr = CoCreateInstance(CLSID_ITStorage, NULL,
  94. CLSCTX_INPROC_SERVER,
  95. IID_ITStorage,
  96. (VOID **) &pITStorage)) &&
  97. SUCCEEDED(hr = pITStorage->StgOpenStorage(lpszMoniker, NULL,
  98. STGM_READ, NULL, 0, &m_pStorage)))
  99. {
  100. hr = Load(m_pStorage);
  101. }
  102. // Free ITSS interface no longer needed
  103. if (pITStorage)
  104. pITStorage->Release();
  105. m_cs.Unlock();
  106. return hr;
  107. }
  108. /********************************************************************
  109. * @method STDMETHODIMP | IITDatabase | Close |
  110. * Closes a database
  111. *
  112. * @rvalue S_OK | The database was successfully closed
  113. *
  114. ********************************************************************/
  115. STDMETHODIMP CITDatabaseLocal::Close()
  116. {
  117. m_cs.Lock();
  118. // release storage pointer
  119. if (m_pStorage)
  120. {
  121. m_pStorage->Release();
  122. m_pStorage = NULL;
  123. }
  124. else
  125. return SetErrReturn(E_NOTINIT);
  126. m_ObjInst.Close();
  127. m_cs.Unlock();
  128. return S_OK;
  129. }
  130. /******************************************************************* *
  131. * @method STDMETHODIMP WINAPI | IITDatabase | CreateObject |
  132. * Creates an unnamed object that can be referenced in the future
  133. * by *pdwObjInstance.
  134. *
  135. * @parm REFCLSID | refclsid | Class ID for object.
  136. * @parm DWORD | *pdwObjInstance | Identifier for object.
  137. *
  138. * @rvalue S_OK | The object was successfully created
  139. * @rvalue E_INVALIDARG | The argument was not valid
  140. * @rvalue E_NOTINIT |
  141. * @rvalue E_OUTOFMEMORY |
  142. *
  143. * @comm
  144. * The value in *pdwObjInstance will be
  145. * persisted by the database when it is asked to save using
  146. * IPersistStorage::Save.
  147. *
  148. ********************************************************************/
  149. STDMETHODIMP
  150. CITDatabaseLocal::CreateObject(REFCLSID rclsid, DWORD *pdwObjInstance)
  151. {
  152. return m_ObjInst.AddObject(rclsid, pdwObjInstance);
  153. }
  154. /******************************************************************* *
  155. * @method STDMETHODIMP WINAPI | IITDatabase | GetObject |
  156. * Retrieves a specified IUnknown-based interface on the object identified
  157. * by dwObjInstance.
  158. *
  159. * @parm DWORD | dwObjInstance | Identifier for object.
  160. * @parm REFIID | refiid | Interface ID
  161. * @parm LPVOID | *ppvObj |
  162. *
  163. * @rvalue S_OK | The operation completed successfully.
  164. * @rvalue E_INVALIDARG | The argument was not valid.
  165. * @rvalue E_NOTINIT |
  166. * @rvalue E_OUTOFMEMORY |
  167. *
  168. *
  169. ********************************************************************/
  170. STDMETHODIMP
  171. CITDatabaseLocal::GetObject(DWORD dwObjInstance, REFIID riid, LPVOID *ppvObj)
  172. {
  173. return m_ObjInst.GetObject(dwObjInstance, riid, ppvObj);
  174. }
  175. /******************************************************************* *
  176. * @method STDMETHODIMP WINAPI | IITDatabase | GetObjectPersistence |
  177. * Retrieves persistence data for a named object.
  178. *
  179. * @parm LPCWSTR | lpwszObject | Name of the object
  180. * @parm DWORD | dwObjInstance | Object instance ID
  181. * @parm LPVOID | *ppvPersistence | Pointer to persistence data for the object.
  182. * @parm BOOL | fStream | Identifies whether the object is a stream object (true)
  183. * or storage object (false).
  184. *
  185. * @rvalue S_OK | The operation completed successfully.
  186. * @rvalue E_INVALIDARG | The argument was not valid.
  187. * @rvalue STG_E_FILENOTFOUND |The specified object's persistence does not
  188. * exist, or it is of the wrong type.
  189. * @rvalue E_NOTINIT |
  190. * @rvalue E_OUTOFMEMORY |
  191. *
  192. * @comm
  193. * To obtain a pointer to a named object's persistence, specify the
  194. * object's full name (including any object-specific type prefix) in
  195. * lpswszObject. If *lpwszObject is NULL, then the database's own storage
  196. * is returned. If lpwszObject is NULL, then dwObjInstance is
  197. * used to identify the object and locate its persistence. On exit,
  198. * *ppvPersistence is either an IStorage* or an IStream*, depending
  199. * on what you specified in the fStream param. Only read operations
  200. * can be performed on *ppvPersistence.
  201. *
  202. ********************************************************************/
  203. STDMETHODIMP
  204. CITDatabaseLocal::GetObjectPersistence(LPCWSTR lpwszObject, DWORD dwObjInstance,
  205. LPVOID *ppvPersistence, BOOL fStream)
  206. {
  207. HRESULT hr = S_OK;
  208. m_cs.Lock();
  209. if (m_pStorage != NULL)
  210. {
  211. if (lpwszObject != NULL)
  212. {
  213. if (fStream)
  214. hr = m_pStorage->OpenStream(lpwszObject, NULL, STGM_READ,
  215. 0, (IStream **) ppvPersistence);
  216. else
  217. {
  218. if (*lpwszObject == (WCHAR) NULL)
  219. {
  220. m_pStorage->AddRef();
  221. *ppvPersistence = (LPVOID) m_pStorage;
  222. }
  223. else
  224. hr = m_pStorage->OpenStorage(lpwszObject, NULL,
  225. STGM_SHARE_DENY_WRITE | STGM_READ,
  226. NULL, 0, (IStorage **) ppvPersistence);
  227. }
  228. }
  229. else
  230. {
  231. if (fStream)
  232. {
  233. // REVIEW (billa, johnrush): Need to allocate memory for the
  234. // object's persistent data and call CreateStreamOnHGlobal.
  235. hr = E_NOTSUPPORTED;
  236. }
  237. else
  238. hr = STG_E_FILENOTFOUND;
  239. }
  240. }
  241. else
  242. hr = E_UNEXPECTED;
  243. m_cs.Unlock();
  244. return (hr);
  245. }
  246. //---------------------------------------------------------------------------
  247. // IPersistStorage Method Implementations
  248. //---------------------------------------------------------------------------
  249. STDMETHODIMP
  250. CITDatabaseLocal::GetClassID(CLSID *pclsid)
  251. {
  252. *pclsid = CLSID_IITDatabaseLocal;
  253. return (S_OK);
  254. }
  255. STDMETHODIMP
  256. CITDatabaseLocal::InitNew(IStorage *pStorage)
  257. {
  258. HRESULT hr = S_OK;
  259. if (pStorage == NULL)
  260. return (E_POINTER);
  261. m_cs.Lock();
  262. if (m_pStorage == NULL)
  263. (m_pStorage = pStorage)->AddRef();
  264. else
  265. hr = E_UNEXPECTED;
  266. m_ObjInst.InitNew();
  267. m_cs.Unlock();
  268. return (hr);
  269. }
  270. STDMETHODIMP
  271. CITDatabaseLocal::IsDirty(void)
  272. {
  273. return m_ObjInst.IsDirty();
  274. }
  275. STDMETHODIMP
  276. CITDatabaseLocal::Load(IStorage *pStorage)
  277. {
  278. HRESULT hr = S_OK;;
  279. if (pStorage == NULL)
  280. return (E_POINTER);
  281. m_cs.Lock();
  282. IStream *pistmObjectManager;
  283. if (FAILED(hr = pStorage->OpenStream
  284. (SZ_OBJINST_STREAM, STGM_READ, 0, 0, &pistmObjectManager)))
  285. return (hr);
  286. hr = m_ObjInst.Load(pistmObjectManager);
  287. pistmObjectManager->Release();
  288. m_cs.Unlock();
  289. return (hr);
  290. }
  291. STDMETHODIMP
  292. CITDatabaseLocal::Save(IStorage *pStorage, BOOL fSameAsLoad)
  293. {
  294. HRESULT hr = S_OK;;
  295. if (pStorage == NULL)
  296. return (E_POINTER);
  297. m_cs.Lock();
  298. IStream *pistmObjectManager;
  299. if (FAILED(hr = pStorage->CreateStream
  300. (SZ_OBJINST_STREAM, STGM_WRITE, 0, 0, &pistmObjectManager)))
  301. return (hr);
  302. hr = m_ObjInst.Save(pistmObjectManager, TRUE);
  303. pistmObjectManager->Release();
  304. m_cs.Unlock();
  305. return (hr);
  306. }
  307. STDMETHODIMP
  308. CITDatabaseLocal::SaveCompleted(IStorage *pStorageNew)
  309. {
  310. if (pStorageNew != NULL)
  311. {
  312. m_cs.Lock();
  313. if (m_pStorage != NULL)
  314. m_pStorage->Release();
  315. (m_pStorage = pStorageNew)->AddRef();
  316. m_cs.Unlock();
  317. }
  318. return (S_OK);
  319. }
  320. STDMETHODIMP
  321. CITDatabaseLocal::HandsOffStorage(void)
  322. {
  323. // REVIEW (billa): At some point, we should implement IPersistStorage
  324. // mode tracking so that we explicitly enter/leave the No Scribble and
  325. // Hands Off Storage modes.
  326. return (S_OK);
  327. }