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.

297 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. 1998 Seagate Software, Inc. All rights reserved
  4. Module Name:
  5. WsbSvc.cpp
  6. Abstract:
  7. This is the implementation of common methods that the Remote Storage
  8. services should utilize.
  9. Author:
  10. Cat Brant [cbrant] 24-Sep-1997
  11. Revision History:
  12. --*/
  13. #include "stdafx.h"
  14. #include "wsbServ.h"
  15. HRESULT
  16. WsbPowerEventNtToHsm(
  17. IN DWORD NtEvent,
  18. OUT ULONG * pHsmEvent
  19. )
  20. /*++
  21. Routine Description:
  22. Convert a NT power event (PBT_APM*) into our state change event.
  23. Arguments:
  24. NtEvent - The PBT_APM* power event.
  25. pHsmEvent - Pointer to HSM change state (combination of
  26. HSM_SYSTEM_STATE_* values)
  27. Return Value:
  28. S_OK - Succes
  29. --*/
  30. {
  31. HRESULT hr = S_OK;
  32. WsbTraceIn(OLESTR("WsbPowerEventNtToHsm"), OLESTR(""));
  33. try {
  34. WsbAffirmPointer(pHsmEvent);
  35. *pHsmEvent = HSM_STATE_NONE;
  36. switch(NtEvent)
  37. {
  38. case PBT_APMQUERYSTANDBY:
  39. case PBT_APMQUERYSUSPEND:
  40. case PBT_APMSTANDBY:
  41. case PBT_APMSUSPEND:
  42. // Suspend operations
  43. *pHsmEvent = HSM_STATE_SUSPEND;
  44. break;
  45. case PBT_APMQUERYSTANDBYFAILED:
  46. case PBT_APMQUERYSUSPENDFAILED:
  47. case PBT_APMRESUMESTANDBY:
  48. case PBT_APMRESUMESUSPEND:
  49. // Resume operations
  50. *pHsmEvent = HSM_STATE_RESUME;
  51. break;
  52. default:
  53. break;
  54. }
  55. } WsbCatch(hr);
  56. WsbTraceOut(OLESTR("WsbPowerEventNtToHsm"), OLESTR("hr = <%ls>"),
  57. WsbHrAsString(hr));
  58. return( hr );
  59. }
  60. HRESULT
  61. WsbServiceSafeInitialize(
  62. IN IWsbServer *pServer,
  63. IN BOOL bVerifyId,
  64. IN BOOL bPrimaryId,
  65. OUT BOOL *pWasCreated
  66. )
  67. /*++
  68. Routine Description:
  69. This function performs various checks to guarantee that the instance of
  70. the service matches the instance that created the existing persistence
  71. files. If this is not the case, the function returns an HRESULT that
  72. indicates where the mismatch occured.
  73. Each service keeps a GUID in the registry and each HSM server object keeps
  74. the same id in its persistence file.
  75. During the initial start (no registry and no persistence file) this
  76. function establishes this match. Upon subsequent starts, this function
  77. guarantees the match of these GUIDs.
  78. It is considered recoverable if the GUID does not exist in the registry
  79. but the persistence file can be found and contains a GUID. In this
  80. situation, this function re-establishes the GUID in the registry. However,
  81. if the GUID is found in the registry and either the persistence file is not
  82. found or the GUID in the persistence file does not match, this function
  83. returns an HRESULT that should prevent the service from running.
  84. Note: Since one service may have several server objects with several persistency files,
  85. there may be some exceptions to the above, according ot the input flags:
  86. 1) bVerifyId sets whether to verify existence of service id in the Registry. Generally,
  87. a service should call with the flag on only once (for the first persistency file loaded).
  88. 2) bPrimaryId sets whether to use this server id as the Registry id. Eventually, this id
  89. becomes the only id in the Registry and all persistency files. Generally, service
  90. should call with the flag on only once (for one of its persistency files).
  91. Arguments:
  92. pServer - pointer to the IWsbServer interface of the Remote Storage
  93. service that is being started
  94. bVerifyId - A flag for whether to verify existence of a file if id is found in the Registry
  95. bPrimaryId - A flag for whether to force equivalence of id and whether to set Registry id according to file id
  96. pWasCreated - if non-NULL, set to TRUE if the persistence file was created.
  97. (If FALSE and return value is S_OK, the file was read.)
  98. Return Value:
  99. S_OK - Success - service startup completed successfully
  100. --*/
  101. {
  102. HRESULT hr = S_OK;
  103. GUID regServerId = GUID_NULL; // GUID of service in registry
  104. GUID dbServerId = GUID_NULL; // GUID of service in database
  105. BOOL foundRegId = FALSE; // Found Service ID in registry
  106. BOOL foundDbId = FALSE; // Found Service ID in database
  107. CWsbStringPtr regName; // Registry Name for service
  108. CWsbStringPtr dbName; // Persistable File name for service
  109. CComPtr<IPersistFile> pServerPersist; // Service's persistable interface
  110. WsbTraceIn(OLESTR("WsbServiceSafeInitialize"), OLESTR(""));
  111. if (pWasCreated) {
  112. *pWasCreated = FALSE;
  113. }
  114. try {
  115. //
  116. // Go to the registry and find the GUID for this service
  117. //
  118. //
  119. // Get the registry name for the service
  120. //
  121. try {
  122. WsbAffirmHr(pServer->GetRegistryName(&regName, 0));
  123. WsbAffirmHr(WsbGetServiceId(regName, &regServerId));
  124. foundRegId = TRUE;
  125. } WsbCatchAndDo( hr, if (WSB_E_NOTFOUND == hr) \
  126. {WsbLogEvent(WSB_MESSAGE_SERVICE_ID_NOT_REGISTERED, 0, NULL, regName, WsbHrAsString(hr), NULL); \
  127. hr = S_OK;};);
  128. WsbAffirmHr( hr );
  129. //
  130. // Locate the persistence file for this service and load it
  131. //
  132. // Get the path to the file and the IPersist Interface
  133. //
  134. try {
  135. WsbAffirmHr(pServer->GetDbPathAndName(&dbName, 0));
  136. WsbAffirmHr(pServer->QueryInterface(IID_IPersistFile, (void **)&pServerPersist));
  137. hr = WsbSafeLoad(dbName, pServerPersist, FALSE);
  138. if (WSB_E_NOTFOUND == hr) {
  139. WsbThrow(hr);
  140. }
  141. // Check the status from the read; WSB_E_NOTFOUND means that
  142. // there was no persistence file found to read
  143. if (!SUCCEEDED(hr)) {
  144. WsbAffirmHr(pServer->Unload());
  145. WsbThrow(hr);
  146. }
  147. WsbAffirmHr(pServer->GetId(&dbServerId));
  148. foundDbId = TRUE;
  149. } WsbCatchAndDo( hr, if (WSB_E_NOTFOUND == hr) \
  150. {WsbLogEvent(WSB_MESSAGE_DATABASES_NOT_FOUND, 0, NULL, regName, WsbHrAsString(hr), NULL); \
  151. hr = S_OK;};);
  152. WsbAffirmHr( hr );
  153. //
  154. // Now evaluate what we have
  155. //
  156. if (foundDbId == TRUE ) {
  157. //
  158. // Got the persistence file, see if things are OK
  159. if (foundRegId == TRUE) {
  160. if (regServerId != dbServerId) {
  161. if (bPrimaryId) {
  162. //
  163. // BIG PROBLEM!!!!! The running instance of the
  164. // server and the persistence file do not match.
  165. // Log a message, STOP the server!
  166. //
  167. hr = WSB_E_SERVICE_INSTANCE_MISMATCH;
  168. WsbLogEvent(WSB_MESSAGE_SERVICE_INSTANCE_MISMATCH, 0, NULL, regName, WsbHrAsString(hr), NULL);
  169. } else {
  170. //
  171. // This may happen once after an upgrade, when the primary id doesn't match all ids:
  172. // Just set the already found (primary) id, after next Save it will be set in all col files
  173. //
  174. WsbAffirmHr(pServer->SetId(regServerId));
  175. }
  176. } else {
  177. //
  178. // Life is good, OK to start
  179. //
  180. }
  181. } else {
  182. //
  183. // We have an ID from the persistence file but there isn't one in
  184. // the registry. So add it to the registry (if it is the primary id) and go on.
  185. //
  186. if (bPrimaryId) {
  187. WsbAffirmHr(WsbSetServiceId(regName, dbServerId));
  188. WsbLogEvent(WSB_MESSAGE_SERVICE_ID_REGISTERED, 0, NULL, regName, WsbHrAsString(hr), NULL);
  189. }
  190. }
  191. } else {
  192. //
  193. // No persistence file was found!
  194. //
  195. if (foundRegId == TRUE) {
  196. if (bVerifyId) {
  197. //
  198. // BIG PROBLEM!!!!! There is a registered instance
  199. // ID but we can't find the file - this is bad.
  200. // Log a warning message
  201. //
  202. hr = WSB_E_SERVICE_MISSING_DATABASES;
  203. WsbLogEvent(WSB_MESSAGE_SERVICE_MISSING_DATABASES, 0, NULL, regName, WsbHrAsString(hr), NULL);
  204. //
  205. // We continue and recreate the col files using the id we found
  206. // That way, truncated files could be recalled even if the original col
  207. // files are completely lost for some reason.
  208. //
  209. hr = S_OK;
  210. }
  211. //
  212. // Just create the persistence file and save the existing id in it
  213. // regServerId contains the found id
  214. //
  215. WsbAffirmHr(pServer->SetId(regServerId));
  216. WsbAffirmHr(WsbSafeCreate(dbName, pServerPersist));
  217. if (pWasCreated) {
  218. *pWasCreated = TRUE;
  219. }
  220. WsbLogEvent(WSB_MESSAGE_SERVICE_NEW_INSTALLATION, 0, NULL, regName, WsbHrAsString(hr), NULL);
  221. } else {
  222. //
  223. // No persistence file and no registry entry - must be a new
  224. // installation. So get a GUID, save it in the registry
  225. // and save it in the file.
  226. //
  227. WsbAffirmHr(WsbCreateServiceId(regName, &regServerId));
  228. WsbAffirmHr(pServer->SetId(regServerId));
  229. WsbAffirmHr(WsbSafeCreate(dbName, pServerPersist));
  230. if (pWasCreated) {
  231. *pWasCreated = TRUE;
  232. }
  233. WsbAffirmHr(WsbConfirmServiceId(regName, regServerId));
  234. WsbLogEvent(WSB_MESSAGE_SERVICE_NEW_INSTALLATION, 0, NULL, regName, WsbHrAsString(hr), NULL);
  235. }
  236. }
  237. } WsbCatch( hr );
  238. WsbTraceOut(OLESTR("WsbServiceSafeInitialize"), OLESTR("hr = <%ls>, wasCreated= %ls"),
  239. WsbHrAsString(hr), WsbPtrToBoolAsString(pWasCreated));
  240. return( hr );
  241. }