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.

381 lines
11 KiB

  1. /////////////////////////////////////////////////////////////////////
  2. //
  3. // StdUtils.cpp
  4. //
  5. // Utilities routines for any snapin.
  6. //
  7. // HISTORY
  8. // t-danmo 96.10.10 Creation.
  9. //
  10. /////////////////////////////////////////////////////////////////////
  11. #include "stdafx.h"
  12. #include "stdutils.h"
  13. /////////////////////////////////////////////////////////////////////
  14. // CompareMachineNames()
  15. //
  16. // Compare if the strings refer to the same machine (computer).
  17. //
  18. // Return 0 if both strings map to the same machine, otherwise
  19. // return -1 or +1 if machine name differs.
  20. //
  21. // INTERFACE NOTES:
  22. // An empty string means the local machine.
  23. //
  24. // HISTORY
  25. // 02-Jun-97 t-danm Creation.
  26. // 14-Jul-97 t-danm Comment update.
  27. // 29-Jul-97 t-danm Renamed from FCompareMachineNames().
  28. //
  29. int
  30. CompareMachineNames(
  31. LPCTSTR pszMachineName1,
  32. LPCTSTR pszMachineName2)
  33. {
  34. TCHAR szThisMachineName[MAX_COMPUTERNAME_LENGTH + 4];
  35. ZeroMemory( szThisMachineName, sizeof(szThisMachineName) ); // JonN 3/28/02
  36. BOOL fMachine1IsLocal = (pszMachineName1 == NULL || *pszMachineName1 == '\0');
  37. BOOL fMachine2IsLocal = (pszMachineName2 == NULL || *pszMachineName2 == '\0');
  38. if (fMachine1IsLocal)
  39. pszMachineName1 = szThisMachineName;
  40. if (fMachine2IsLocal)
  41. pszMachineName2 = szThisMachineName;
  42. if (pszMachineName1 == pszMachineName2)
  43. return 0;
  44. if (fMachine1IsLocal || fMachine2IsLocal)
  45. {
  46. // Get the computer name
  47. szThisMachineName[0] = _T('\\');
  48. szThisMachineName[1] = _T('\\');
  49. DWORD cchBuffer = MAX_COMPUTERNAME_LENGTH + 1;
  50. VERIFY(::GetComputerName(OUT &szThisMachineName[2], &cchBuffer));
  51. ASSERT(szThisMachineName[2] != _T('\\') && "Machine name has too many backslashes");
  52. }
  53. return lstrcmpi(pszMachineName1, pszMachineName2);
  54. } // CompareMachineNames()
  55. /////////////////////////////////////////////////////////////////////
  56. // HrLoadOleString()
  57. //
  58. // Load a string from the resource and return pointer to allocated
  59. // OLE string.
  60. //
  61. // HISTORY
  62. // 29-Jul-97 t-danm Creation.
  63. //
  64. HRESULT
  65. HrLoadOleString(
  66. UINT uStringId, // IN: String Id to load from the resource
  67. OUT LPOLESTR * ppaszOleString) // OUT: Pointer to pointer to allocated OLE string
  68. {
  69. if (ppaszOleString == NULL)
  70. {
  71. TRACE0("HrLoadOleString() - ppaszOleString is NULL.\n");
  72. return E_POINTER;
  73. }
  74. CString strT; // Temporary string
  75. // ISSUE-2002/03/28-JonN should call HrCopyToOleString
  76. AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Needed for LoadString()
  77. VERIFY( strT.LoadString(uStringId) );
  78. *ppaszOleString = reinterpret_cast<LPOLESTR>
  79. (CoTaskMemAlloc((strT.GetLength() + 1)* sizeof(wchar_t)));
  80. if (*ppaszOleString == NULL)
  81. return E_OUTOFMEMORY;
  82. // ISSUE-2002/03/28-JonN I don't entirely trust this USES_CONVERSION stuff
  83. USES_CONVERSION;
  84. wcscpy(OUT *ppaszOleString, T2OLE((LPTSTR)(LPCTSTR)strT));
  85. return S_OK;
  86. } // HrLoadOleString()
  87. /////////////////////////////////////////////////////////////////////
  88. // HrCopyToOleString()
  89. //
  90. // Copies a CString into an allocated
  91. // OLE string.
  92. //
  93. // HISTORY
  94. // 05-Jun-2001 jeffjon Creation.
  95. //
  96. HRESULT
  97. HrCopyToOleString(
  98. const CString& strT, // IN: String Id to load from the resource
  99. OUT LPOLESTR * ppaszOleString) // OUT: Pointer to pointer to allocated OLE string
  100. {
  101. if (ppaszOleString == NULL)
  102. {
  103. TRACE0("HrLoadOleString() - ppaszOleString is NULL.\n");
  104. return E_POINTER;
  105. }
  106. AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Needed for LoadString()
  107. *ppaszOleString = reinterpret_cast<LPOLESTR>
  108. (CoTaskMemAlloc((strT.GetLength() + 1)* sizeof(wchar_t)));
  109. if (*ppaszOleString == NULL)
  110. {
  111. return E_OUTOFMEMORY;
  112. }
  113. USES_CONVERSION;
  114. wcscpy(OUT *ppaszOleString, T2OLE((LPTSTR)(LPCTSTR)strT));
  115. return S_OK;
  116. } // HrCopyToOleString()
  117. //
  118. // Nodetype utility routines
  119. // aNodetypeGuids must be defined by the subclass
  120. //
  121. int CheckObjectTypeGUID( const BSTR lpszObjectTypeGUID )
  122. {
  123. ASSERT(NULL != lpszObjectTypeGUID);
  124. if (NULL == lpszObjectTypeGUID) // JonN 2002/03/28
  125. return 0;
  126. for ( int objecttype = 0;
  127. objecttype < g_cNumNodetypeGuids;
  128. objecttype += 1 )
  129. {
  130. if ( !::lstrcmpiW(lpszObjectTypeGUID,g_aNodetypeGuids[objecttype].bstr) )
  131. return objecttype;
  132. }
  133. ASSERT( FALSE );
  134. return 0;
  135. }
  136. int CheckObjectTypeGUID( const GUID* pguid )
  137. {
  138. ASSERT(NULL != pguid);
  139. if (NULL == pguid) // JonN 2002/03/28
  140. return 0;
  141. for ( int objecttype = 0;
  142. objecttype < g_cNumNodetypeGuids;
  143. objecttype += 1 )
  144. {
  145. if ( g_aNodetypeGuids[objecttype].guid == *pguid )
  146. return objecttype;
  147. }
  148. ASSERT( FALSE );
  149. return 0;
  150. }
  151. /////////////////////////////////////////////////////////////////////
  152. // FilemgmtCheckObjectTypeGUID()
  153. //
  154. // Compare the GUID and return the objecttype associated with
  155. // the guid.
  156. // If no match found, return -1.
  157. //
  158. // HISTORY
  159. // 14-Jul-97 t-danm Creation. Inspired from CheckObjectTypeGUID()
  160. // but does not assert if the GUID is not found.
  161. //
  162. int FilemgmtCheckObjectTypeGUID(const GUID* pguid )
  163. {
  164. ASSERT(NULL != pguid);
  165. if (NULL == pguid) // JonN 2002/03/28
  166. return -1;
  167. for ( int objecttype = 0;
  168. objecttype < g_cNumNodetypeGuids;
  169. objecttype += 1 )
  170. {
  171. if ( g_aNodetypeGuids[objecttype].guid == *pguid )
  172. return objecttype;
  173. }
  174. return -1;
  175. } // FilemgmtCheckObjectTypeGUID()
  176. const BSTR GetObjectTypeString( int objecttype )
  177. {
  178. if (objecttype < 0 || objecttype >= g_cNumNodetypeGuids)
  179. {
  180. ASSERT( FALSE );
  181. objecttype = 0;
  182. }
  183. return g_aNodetypeGuids[objecttype].bstr;
  184. }
  185. const GUID* GetObjectTypeGUID( int objecttype )
  186. {
  187. if (objecttype < 0 || objecttype >= g_cNumNodetypeGuids)
  188. {
  189. ASSERT( FALSE );
  190. objecttype = 0;
  191. }
  192. return &(g_aNodetypeGuids[objecttype].guid);
  193. }
  194. //+---------------------------------------------------------------------------
  195. //
  196. // Function: SynchronousCreateProcess
  197. //
  198. // Synopsis: Invoke a separate UI process as a modal window.
  199. //
  200. //----------------------------------------------------------------------------
  201. HRESULT SynchronousCreateProcess(
  202. HWND hWnd,
  203. LPCTSTR pszAppName,
  204. LPCTSTR pszCommandLine,
  205. LPDWORD lpdwExitCode
  206. )
  207. {
  208. HRESULT hr = S_OK;
  209. BOOL bReturn = FALSE;
  210. STARTUPINFO si;
  211. PROCESS_INFORMATION pi;
  212. //
  213. // disable the MMC main frame window to prevent it from
  214. // being shut down. The process we're going to create must
  215. // display a UI, such that, it behaves like a modal window.
  216. //
  217. ::EnableWindow(hWnd, FALSE);
  218. *lpdwExitCode = 0;
  219. ZeroMemory(&si, sizeof(STARTUPINFO));
  220. si.cb = sizeof(STARTUPINFO);
  221. bReturn = CreateProcess(
  222. pszAppName, //LPCTSTR lpApplicationName
  223. const_cast<LPTSTR>(pszCommandLine), //LPTSTR lpCommandLine
  224. NULL, //LPSECURITY_ATTRIBUTES lpProcessAttributes
  225. NULL, //LPSECURITY_ATTRIBUTES lpThreadAttributes
  226. FALSE, //BOOL bInheritHandles
  227. NORMAL_PRIORITY_CLASS, //DWORD dwCreationFlags
  228. NULL, //LPVOID lpEnvironment
  229. NULL, //lpCurrentDirectory
  230. &si, //LPSTARTUPINFO lpStartupInfo
  231. &pi //LPPROCESS_INFORMATION lpProcessInformation
  232. );
  233. if (!bReturn)
  234. {
  235. hr = HRESULT_FROM_WIN32(GetLastError());
  236. } else
  237. {
  238. //
  239. // while process is still running, pump message to MMC main window,
  240. // such that it will repaint itself
  241. //
  242. while (TRUE)
  243. {
  244. MSG tempMSG;
  245. DWORD dwWait;
  246. while(::PeekMessage(&tempMSG,NULL, 0, 0, PM_REMOVE))
  247. DispatchMessage(&tempMSG);
  248. dwWait = MsgWaitForMultipleObjects(1, &(pi.hProcess), FALSE, INFINITE, QS_ALLINPUT);
  249. if ( 0 == (dwWait - WAIT_OBJECT_0))
  250. break; // process is done
  251. };
  252. bReturn = GetExitCodeProcess(pi.hProcess, lpdwExitCode);
  253. if (!bReturn)
  254. hr = HRESULT_FROM_WIN32(GetLastError());
  255. CloseHandle(pi.hThread);
  256. CloseHandle(pi.hProcess);
  257. }
  258. //
  259. // enable MMC main frame window before return
  260. //
  261. ::EnableWindow(hWnd, TRUE);
  262. return hr;
  263. }
  264. /*
  265. This code is not working yet. The problem is that it hangs the
  266. message loop, preventing redraw. One possible approach is to disable the
  267. top-level window and spin off a thread which waits for the process to stop,
  268. then the thread reenables the top-level window and calls UpdateAllViews.
  269. DWORD WINAPI ProcessMonitor(LPVOID pv)
  270. {
  271. }
  272. class CSyncThread : public CThread
  273. {
  274. };
  275. HRESULT SynchronousCreateProcess(LPCTSTR cpszCommandLine,
  276. SynchronousProcessCompletionRoutine pfunc,
  277. PVOID pvFuncParams)
  278. // does not handle completion routine
  279. {
  280. PROCESS_INFORMATION piProcInfo;
  281. (void) ::memset(&piProcInfo,0,sizeof(piProcInfo));
  282. STARTUPINFO si;
  283. (void) ::memset(&si,0,sizeof(si));
  284. ::GetStartupInfo( &si );
  285. //
  286. // MarkL 1/30/97: Is pszCommandLine a static string?
  287. // It can not be read only. It is modified temporarily by the call
  288. // if you do not specify lpszImageName. There is no query to see
  289. // if a process is running. You can test to see if it has exited
  290. // using waitforsingleobject to see if the process object is signaled.
  291. //
  292. // MarkL also confirms that the handle should absolutely always
  293. // be signalled when the process dies.
  294. //
  295. LPTSTR pszCommandLine = (LPTSTR)
  296. ::alloca(sizeof(TCHAR)*(::_tcslen(cpszCommandLine)+1));
  297. ::_tcscpy(pszCommandLine,cpszCommandLine);
  298. if ( !::CreateProcess(
  299. NULL, // LPCTSTR lpszImageName
  300. pszCommandLine, // LPTSTR lpszCommandLine
  301. NULL, // LPSECURITY_ATTRIBUTES lpsaProcess
  302. NULL, // LPSECURITY_ATTRIBUTES lpsaThread
  303. FALSE, // BOOL fInheritHandles
  304. 0L, // DWORD fdwCreate
  305. NULL, // LPVOID lpvEnvironment
  306. NULL, // LPTSTR lpszCurDir
  307. &si, // LPSTARTUPINFO lpsiStartInfo
  308. &piProcInfo // LPPROCESS_INFORMATION lppiProcInfo
  309. ) )
  310. {
  311. DWORD dwErr = ::GetLastError();
  312. ASSERT( ERROR_SUCCESS != dwErr );
  313. return HRESULT_FROM_WIN32(dwErr);
  314. }
  315. ASSERT( NULL != piProcInfo.hProcess );
  316. VERIFY( WAIT_OBJECT_0 ==
  317. ::WaitForSingleObject( piProcInfo.hProcess, INFINITE ) );
  318. VERIFY( ::CloseHandle( piProcInfo.hProcess ) );
  319. VERIFY( ::CloseHandle( piProcInfo.hThread ) );
  320. return S_OK;
  321. }
  322. */
  323. // ISSUE-2002/03/28-JonN duplicates HrCopyToOleString
  324. LPOLESTR CoTaskAllocString( LPCOLESTR psz )
  325. {
  326. if (NULL == psz)
  327. return NULL;
  328. LPOLESTR pszReturn = (LPOLESTR)CoTaskMemAlloc( (lstrlen(psz)+1)*sizeof(OLECHAR) );
  329. if (NULL != pszReturn)
  330. lstrcpy( pszReturn, psz );
  331. ASSERT( NULL != pszReturn );
  332. return pszReturn;
  333. }
  334. // ISSUE-2002/03/28-JonN duplicates HrLoadOleString
  335. LPOLESTR CoTaskLoadString( UINT nResourceID )
  336. {
  337. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  338. // load the resource
  339. CString strText;
  340. strText.LoadString( nResourceID );
  341. ASSERT( !strText.IsEmpty() );
  342. return CoTaskAllocString( const_cast<BSTR>((LPCTSTR)strText) );
  343. }