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.

338 lines
8.3 KiB

  1. // ***************************************************************************
  2. // Copyright (C) 2000- Microsoft Corporation.
  3. // @File: sqlenum.cpp
  4. //
  5. // PURPOSE:
  6. //
  7. // Enumerate the sqlservers available on the local node.
  8. //
  9. // NOTES:
  10. //
  11. //
  12. // HISTORY:
  13. //
  14. // @Version: Whistler/Shiloh
  15. // 76910 SRS 08/08/01 Rollforward from VSS snapshot
  16. // 68228 12/05/00 ntsnap work
  17. // 68067 srs 11/06/00 ntsnap fix
  18. // 67026 srs 10/05/00 Server enumeration bugs
  19. //
  20. //
  21. // @EndHeader@
  22. // ***************************************************************************
  23. #ifdef HIDE_WARNINGS
  24. #pragma warning( disable : 4786)
  25. #endif
  26. #include <stdafx.h>
  27. #include <clogmsg.h>
  28. ////////////////////////////////////////////////////////////////////////
  29. // Standard foo for file name aliasing. This code block must be after
  30. // all includes of VSS header files.
  31. //
  32. #ifdef VSS_FILE_ALIAS
  33. #undef VSS_FILE_ALIAS
  34. #endif
  35. #define VSS_FILE_ALIAS "SQLENUMC"
  36. //
  37. ////////////////////////////////////////////////////////////////////////
  38. //------------------------------------------------------------------------
  39. // Determine if the given service name is for a sql server instance.
  40. // If so, return TRUE, the version (7,8,9) and the name of the server
  41. // The servername is the name used to connect to the server.
  42. // This will always be of the form: <ComputerName> [\<NamedInstanceName>]
  43. // On a cluster, the ComputerName is a virtual server name.
  44. //
  45. BOOL // TRUE if the service is a sqlserver instance
  46. IsSQL (
  47. PCWSTR pServiceName, // in: name of a service
  48. UINT* pVersion, // out: version of the sql instance
  49. WString& serverName) // out: servername to use to connect to instance
  50. {
  51. BOOL isDefault = FALSE;
  52. PCWSTR pInstanceName = NULL;
  53. if (_wcsicmp (pServiceName, L"MSSQLSERVER") != 0)
  54. {
  55. if (_wcsnicmp (pServiceName, L"MSSQL$", 6) != 0)
  56. {
  57. return FALSE;
  58. }
  59. // we have a named instance
  60. //
  61. pInstanceName = pServiceName+6;
  62. isDefault = FALSE;
  63. }
  64. else
  65. {
  66. // default instance.... pInstanceName remains null...
  67. isDefault = TRUE;
  68. }
  69. WString rootKey = L"Software\\Microsoft\\";
  70. if (isDefault)
  71. {
  72. rootKey += L"MSSQLServer";
  73. }
  74. else
  75. {
  76. rootKey += L"Microsoft SQL Server\\" + WString (pInstanceName);
  77. }
  78. // First determine the "machinename".
  79. // when clustered, we pull the the virtual server name from the registry.
  80. //
  81. BOOL isClustered = FALSE;
  82. WString keyName = rootKey + L"\\Cluster";
  83. HKEY regHandle;
  84. if (RegOpenKeyExW (
  85. HKEY_LOCAL_MACHINE,
  86. keyName.c_str (),
  87. 0, KEY_QUERY_VALUE, &regHandle) == ERROR_SUCCESS)
  88. {
  89. #define MAX_CLUSTER_NAME 256
  90. DWORD keytype;
  91. WCHAR clusterName [MAX_CLUSTER_NAME+1];
  92. DWORD valueLen = sizeof (clusterName)- sizeof(WCHAR);
  93. clusterName[MAX_CLUSTER_NAME] = L'\0';
  94. if (RegQueryValueExW (
  95. regHandle, L"ClusterName",
  96. NULL, &keytype, (LPBYTE) clusterName,
  97. &valueLen) == ERROR_SUCCESS &&
  98. keytype == REG_SZ)
  99. {
  100. isClustered = TRUE;
  101. serverName = WString(clusterName);
  102. }
  103. RegCloseKey (regHandle);
  104. }
  105. if (!isClustered)
  106. {
  107. WCHAR compName [MAX_COMPUTERNAME_LENGTH + 2];
  108. DWORD nameLen = MAX_COMPUTERNAME_LENGTH + 1;
  109. if (!GetComputerNameW (compName, &nameLen))
  110. {
  111. // In the unlikely event that this fails,
  112. // let's just use '.'
  113. //
  114. compName [0] = L'.';
  115. compName [1] = 0;
  116. }
  117. serverName = compName;
  118. }
  119. // For named instances, append the instance name to the "machine" name.
  120. //
  121. if (!isDefault)
  122. {
  123. serverName += L"\\" + WString (pInstanceName);
  124. }
  125. *pVersion = 9; // assume post sql2000 if we can't tell
  126. keyName = rootKey + L"\\MSSQLServer\\CurrentVersion";
  127. if (RegOpenKeyExW (
  128. HKEY_LOCAL_MACHINE,
  129. keyName.c_str (),
  130. 0, KEY_QUERY_VALUE, &regHandle) == ERROR_SUCCESS)
  131. {
  132. DWORD keytype;
  133. const bufferSize = 20;
  134. WCHAR versionString [bufferSize+1];
  135. DWORD valueLen = sizeof (versionString) - sizeof(WCHAR);
  136. versionString[bufferSize] = L'\0';
  137. if (RegQueryValueExW (
  138. regHandle, L"CurrentVersion",
  139. NULL, &keytype, (LPBYTE) versionString,
  140. &valueLen) == ERROR_SUCCESS &&
  141. keytype == REG_SZ)
  142. {
  143. swscanf (versionString, L"%d", pVersion);
  144. }
  145. RegCloseKey (regHandle);
  146. }
  147. return TRUE;
  148. }
  149. //------------------------------------------------------------------------
  150. // Build the list of servers on the current machine.
  151. // Throws exception if any errors occur.
  152. //
  153. StringVector*
  154. EnumerateServers ()
  155. {
  156. CVssFunctionTracer ft(VSSDBG_SQLLIB, L"EnumerateServers");
  157. RETCODE rc;
  158. BYTE* pBuf = NULL;
  159. std::auto_ptr<StringVector> serverList (new StringVector);
  160. SC_HANDLE hSCManager = NULL;
  161. BOOL restrict2000 = FALSE;
  162. // Read a registry key to see if we should avoid sql versions
  163. // beyond SQL2000.
  164. //
  165. {
  166. CVssRegistryKey restrictKey (KEY_QUERY_VALUE);
  167. if (restrictKey.Open (HKEY_LOCAL_MACHINE, x_wszVssCASettingsPath))
  168. {
  169. DWORD val;
  170. if (restrictKey.GetValue (L"MSDEVersionChecking", val, FALSE))
  171. {
  172. if (val != 0)
  173. {
  174. restrict2000 = TRUE;
  175. ft.Trace(VSSDBG_SQLLIB, L"Restricting Enumeration - MSDE writer will skip every SQL version newer than 2000");
  176. }
  177. }
  178. restrictKey.Close ();
  179. }
  180. }
  181. try
  182. {
  183. // open SCM
  184. //
  185. hSCManager = OpenSCManagerW (NULL, NULL,
  186. SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);
  187. if (hSCManager == NULL )
  188. ft.TranslateWin32Error(VSSDBG_SQLLIB, L"OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT)");
  189. LPENUM_SERVICE_STATUSW pServStat;
  190. DWORD bytesNeeded;
  191. DWORD sizeOfBuffer;
  192. DWORD entriesReturned;
  193. DWORD resumeHandle = 0;
  194. DWORD status;
  195. EnumServicesStatusW (hSCManager,
  196. SERVICE_WIN32,
  197. SERVICE_ACTIVE,
  198. NULL,
  199. 0,
  200. &bytesNeeded,
  201. &entriesReturned,
  202. &resumeHandle);
  203. status = GetLastError ();
  204. if (status != ERROR_MORE_DATA)
  205. ft.TranslateWin32Error(VSSDBG_SQLLIB, L"EnumServicesStatus(SERVICE_WIN32, SERVICE_STATE_ALL, ...)");
  206. sizeOfBuffer = bytesNeeded;
  207. pBuf = new BYTE [sizeOfBuffer]; // "new" will throw on err
  208. BOOL moreExpected = FALSE;
  209. do
  210. {
  211. pServStat = (LPENUM_SERVICE_STATUSW)pBuf;
  212. moreExpected = FALSE;
  213. if (!EnumServicesStatusW (hSCManager,
  214. SERVICE_WIN32,
  215. SERVICE_ACTIVE,
  216. pServStat,
  217. sizeOfBuffer,
  218. &bytesNeeded,
  219. &entriesReturned,
  220. &resumeHandle))
  221. {
  222. status = GetLastError ();
  223. if (status != ERROR_MORE_DATA)
  224. ft.TranslateWin32Error(VSSDBG_SQLLIB, L"EnumServicesStatus(SERVICE_WIN32, SERVICE_STATE_ALL, ...)");
  225. moreExpected = TRUE;
  226. }
  227. while (entriesReturned-- > 0)
  228. {
  229. UINT version = 0;
  230. WString serverName;
  231. // We only need the running servers.
  232. //
  233. if (pServStat->ServiceStatus.dwCurrentState == SERVICE_RUNNING)
  234. {
  235. if (IsSQL (pServStat->lpServiceName, &version, serverName))
  236. {
  237. ft.Trace(VSSDBG_SQLLIB, L"Service: %s Server: %s. Version=%d\n",
  238. pServStat->lpServiceName, serverName.c_str (), version);
  239. if (version >= 7)
  240. {
  241. if (version < 9 || !restrict2000)
  242. {
  243. serverList->push_back (serverName);
  244. }
  245. }
  246. }
  247. }
  248. pServStat++;
  249. }
  250. }
  251. while (moreExpected);
  252. if (pBuf)
  253. {
  254. delete [] pBuf;
  255. }
  256. if (hSCManager)
  257. {
  258. CloseServiceHandle (hSCManager);
  259. }
  260. }
  261. catch (HRESULT)
  262. {
  263. if (pBuf)
  264. {
  265. delete [] pBuf;
  266. }
  267. if (hSCManager)
  268. {
  269. CloseServiceHandle (hSCManager);
  270. }
  271. throw;
  272. }
  273. catch (std::exception)
  274. {
  275. if (pBuf)
  276. {
  277. delete [] pBuf;
  278. }
  279. if (hSCManager)
  280. {
  281. CloseServiceHandle (hSCManager);
  282. }
  283. throw;
  284. }
  285. return serverList.release();
  286. }