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.

515 lines
14 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corp., 1997 **/
  4. /**********************************************************************/
  5. /*
  6. sfmutil.cpp
  7. Misc utility routines for SFM dialogs/property pages
  8. FILE HISTORY:
  9. 8/20/97 ericdav Code moved into file managemnet snapin
  10. */
  11. #include "stdafx.h"
  12. #include "sfmutil.h"
  13. #include "sfmcfg.h"
  14. #include "sfmsess.h"
  15. #include "sfmfasoc.h"
  16. #include "macros.h" // MFC_TRY/MFC_CATCH
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. TCHAR c_szSoftware[] = _T("Software");
  23. TCHAR c_szMicrosoft[] = _T("Microsoft");
  24. TCHAR c_szWindowsNT[] = _T("Windows NT");
  25. TCHAR c_szCurrentVersion[] = _T("CurrentVersion");
  26. ULONG arrayHelpIDs_CONFIGURE_SFM[]=
  27. {
  28. IDC_BUTTON_ADD, HIDC_BUTTON_ADD, // File Association: "A&dd..." (Button)
  29. IDC_BUTTON_EDIT, HIDC_BUTTON_EDIT, // File Association: "&Edit..." (Button)
  30. IDC_COMBO_CREATOR, HIDC_COMBO_CREATOR, // Add Document Type: "" (ComboBox)
  31. IDC_BUTTON_DELETE, HIDC_BUTTON_DELETE, // File Association: "De&lete" (Button)
  32. IDC_BUTTON_ASSOCIATE, HIDC_BUTTON_ASSOCIATE, // File Association: "&Associate" (Button)
  33. IDC_COMBO_FILE_TYPE, HIDC_COMBO_FILE_TYPE, // Add Document Type: "" (ComboBox)
  34. IDC_LIST_TYPE_CREATORS, HIDC_LIST_TYPE_CREATORS, // File Association: "" (ListBox)
  35. IDC_EDIT_LOGON_MESSAGE, HIDC_EDIT_LOGON_MESSAGE, // Configuration: "" (Edit)
  36. IDC_COMBO_AUTHENTICATION, HIDC_COMBO_AUTHENTICATION, // Configuration: "Authentication type combo box"
  37. IDC_CHECK_SAVE_PASSWORD, HIDC_CHECK_SAVE_PASSWORD, // Configuration: "Allow &Workstations to Save Password" (Button)
  38. IDC_RADIO_SESSION_UNLIMITED,HIDC_RADIO_SESSION_UNLIMITED,// Configuration: "&Unlimited" (Button)
  39. IDC_RADIO_SESSSION_LIMIT, HIDC_RADIO_SESSSION_LIMIT, // Configuration: "Li&mit to" (Button)
  40. IDC_BUTTON_SEND, HIDC_BUTTON_SEND, // Sessions: "&Send" (Button)
  41. IDC_EDIT_MESSAGE, HIDC_EDIT_MESSAGE, // Sessions: "" (Edit)
  42. IDC_STATIC_SESSIONS, HIDC_STATIC_SESSIONS, // Sessions: "Static" (Static)
  43. IDC_EDIT_DESCRIPTION, HIDC_EDIT_DESCRIPTION, // Add Document Type: "" (Edit)
  44. IDC_STATIC_FORKS, HIDC_STATIC_FORKS, // Sessions: "Static" (Static)
  45. IDC_STATIC_FILE_LOCKS, HIDC_STATIC_FILE_LOCKS, // Sessions: "Static" (Static)
  46. IDC_STATIC_CREATOR, HIDC_STATIC_CREATOR, // Edit Document Type: "Static" (Static)
  47. IDC_EDIT_SERVER_NAME, HIDC_EDIT_SERVER_NAME, // Configuration: "" (Edit)
  48. IDC_COMBO_EXTENSION, HIDC_COMBO_EXTENSION, // File Association: "" (ComboBox)
  49. IDC_EDIT_SESSION_LIMIT, HIDC_EDIT_SESSION_LIMIT, // Configuration: "0" (Edit)
  50. IDC_SFM_EDIT_PASSWORD, HIDC_SFM_EDIT_PASSWORD,
  51. IDC_SFM_CHECK_READONLY, HIDC_SFM_CHECK_READONLY,
  52. (ULONG)IDC_STATIC, (ULONG)-1,
  53. 0, 0
  54. };
  55. // these are the only controls we care about....
  56. const ULONG_PTR g_aHelpIDs_CONFIGURE_SFM = (ULONG_PTR)&arrayHelpIDs_CONFIGURE_SFM[0];
  57. USE_HANDLE_MACROS("FILEMGMT(sfmutil.cpp)")
  58. HRESULT
  59. GetErrorMessageFromModule(
  60. IN DWORD dwError,
  61. IN LPCTSTR lpszDll,
  62. OUT LPTSTR *ppBuffer
  63. )
  64. {
  65. if (0 == dwError || !lpszDll || !*lpszDll || !ppBuffer)
  66. return E_INVALIDARG;
  67. HRESULT hr = S_OK;
  68. HINSTANCE hMsgLib = LoadLibrary(lpszDll);
  69. if (!hMsgLib)
  70. hr = HRESULT_FROM_WIN32(GetLastError());
  71. else
  72. {
  73. DWORD dwRet = ::FormatMessage(
  74. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  75. hMsgLib, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  76. (LPTSTR)ppBuffer, 0, NULL);
  77. if (0 == dwRet)
  78. hr = HRESULT_FROM_WIN32(GetLastError());
  79. FreeLibrary(hMsgLib);
  80. }
  81. return hr;
  82. }
  83. HRESULT
  84. GetErrorMessage(
  85. IN DWORD i_dwError,
  86. OUT CString& cstrErrorMsg
  87. )
  88. {
  89. if (0 == i_dwError)
  90. return E_INVALIDARG;
  91. HRESULT hr = S_OK;
  92. LPTSTR lpBuffer = NULL;
  93. DWORD dwRet = ::FormatMessage(
  94. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  95. NULL, i_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  96. (LPTSTR)&lpBuffer, 0, NULL);
  97. if (0 == dwRet)
  98. {
  99. // if no message is found, GetLastError will return ERROR_MR_MID_NOT_FOUND
  100. hr = HRESULT_FROM_WIN32(GetLastError());
  101. if (HRESULT_FROM_WIN32(ERROR_MR_MID_NOT_FOUND) == hr ||
  102. 0x80070000 == (i_dwError & 0xffff0000) ||
  103. 0 == (i_dwError & 0xffff0000) )
  104. {
  105. hr = GetErrorMessageFromModule((i_dwError & 0x0000ffff), _T("netmsg.dll"), &lpBuffer);
  106. if (HRESULT_FROM_WIN32(ERROR_MR_MID_NOT_FOUND) == hr)
  107. {
  108. int iError = i_dwError; // convert to a signed integer
  109. if (iError >= AFPERR_MIN && iError < AFPERR_BASE)
  110. {
  111. // use a positive number to search sfmmsg.dll
  112. hr = GetErrorMessageFromModule(-iError, _T("sfmmsg.dll"), &lpBuffer);
  113. }
  114. }
  115. }
  116. }
  117. if (SUCCEEDED(hr))
  118. {
  119. cstrErrorMsg = lpBuffer;
  120. LocalFree(lpBuffer);
  121. }
  122. else
  123. {
  124. // we failed to retrieve the error message from system/netmsg.dll/sfmmsg.dll,
  125. // report the error code directly to user
  126. hr = S_OK;
  127. cstrErrorMsg.Format(_T("0x%x"), i_dwError);
  128. }
  129. return S_OK;
  130. }
  131. void SFMMessageBox(DWORD dwErrCode)
  132. {
  133. HRESULT hr = S_OK;
  134. CString strMessage;
  135. if (!dwErrCode)
  136. return; // not expected
  137. hr = GetErrorMessage(dwErrCode, strMessage);
  138. if (FAILED(hr))
  139. {
  140. // Failed to retrieve the proper message, report the failure directly to user
  141. strMessage.Format(_T("0x%x"), hr);
  142. }
  143. AfxMessageBox(strMessage);
  144. }
  145. BOOL CALLBACK EnumThreadWndProc(HWND hwnd, /* enumerated HWND */
  146. LPARAM lParam /* pass a HWND* for return value*/ )
  147. {
  148. _ASSERTE(hwnd);
  149. HWND hParentWnd = GetParent(hwnd);
  150. // the main window of the MMC console should staitsfy this condition
  151. if ( ((hParentWnd == GetDesktopWindow()) || (hParentWnd == NULL)) && IsWindowVisible(hwnd) )
  152. {
  153. HWND* pH = (HWND*)lParam;
  154. *pH = hwnd;
  155. return FALSE; // stop enumerating
  156. }
  157. return TRUE;
  158. }
  159. HWND FindMMCMainWindow()
  160. {
  161. DWORD dwThreadID = ::GetCurrentThreadId();
  162. _ASSERTE(dwThreadID != 0);
  163. HWND hWnd = NULL;
  164. BOOL bEnum = EnumThreadWindows(dwThreadID, EnumThreadWndProc,(LPARAM)&hWnd);
  165. _ASSERTE(hWnd != NULL);
  166. return hWnd;
  167. }
  168. /////////////////////////////////////////////////////////////////////
  169. // Constructor for CSFMPropertySheet object
  170. CSFMPropertySheet::CSFMPropertySheet()
  171. {
  172. m_pPageConfig = new CMacFilesConfiguration;
  173. m_pPageConfig->m_pSheet = this;
  174. m_pPageSessions = new CMacFilesSessions;
  175. m_pPageSessions->m_pSheet = this;
  176. m_pPageFileAssoc = new CMacFilesFileAssociation;
  177. m_pPageFileAssoc->m_pSheet = this;
  178. m_hSheetWindow = NULL;
  179. m_hThread = NULL;
  180. m_nRefCount =1;
  181. } // CSFMPropertySheet::CSFMPropertySheet()
  182. CSFMPropertySheet::~CSFMPropertySheet()
  183. {
  184. delete m_pPageConfig;
  185. delete m_pPageSessions;
  186. delete m_pPageFileAssoc;
  187. if (m_hDestroySync)
  188. {
  189. CloseHandle(m_hDestroySync);
  190. m_hDestroySync = NULL;
  191. }
  192. } // CServicePropertyData::~CServicePropertyData()
  193. BOOL
  194. CSFMPropertySheet::FInit
  195. (
  196. LPDATAOBJECT lpDataObject,
  197. AFP_SERVER_HANDLE hAfpServer,
  198. LPCTSTR pSheetTitle,
  199. SfmFileServiceProvider * pSfmProvider,
  200. LPCTSTR pMachine
  201. )
  202. {
  203. m_spDataObject = lpDataObject;
  204. m_strTitle = pSheetTitle;
  205. m_hAfpServer = hAfpServer;
  206. m_pSfmProvider = pSfmProvider;
  207. m_strHelpFilePath = _T("sfmmgr.hlp"); // does not need to be localized
  208. m_strMachine = pMachine;
  209. m_hDestroySync = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  210. if (!m_hDestroySync)
  211. return FALSE;
  212. return TRUE;
  213. }
  214. BOOL
  215. CSFMPropertySheet::DoModelessSheet(LPDATAOBJECT pDataObject)
  216. {
  217. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  218. LPPROPERTYSHEETCALLBACK pCallback = NULL;
  219. LPPROPERTYSHEETPROVIDER pProvider = NULL;
  220. HPROPSHEETPAGE hPage;
  221. HRESULT hr = S_OK;
  222. HWND hWnd;
  223. BOOL bReturn = TRUE;
  224. // get the property sheet provider interface
  225. hr = ::CoCreateInstance(CLSID_NodeManager, NULL, CLSCTX_INPROC,
  226. IID_IPropertySheetProvider, reinterpret_cast<void **>(&pProvider));
  227. if (FAILED(hr))
  228. return FALSE;
  229. _ASSERTE(pProvider != NULL);
  230. // get an interface to a sheet callback
  231. hr = pProvider->QueryInterface(IID_IPropertySheetCallback, (void**) &pCallback);
  232. if (FAILED(hr))
  233. {
  234. bReturn = FALSE;
  235. goto Error;
  236. }
  237. _ASSERTE(pCallback != NULL);
  238. // create sheet
  239. hr = pProvider->CreatePropertySheet(m_strTitle,
  240. TRUE /* prop page */,
  241. NULL,
  242. //m_spDataObject,
  243. pDataObject,
  244. 0);
  245. // add pages to sheet - config
  246. MMCPropPageCallback(INOUT &m_pPageConfig->m_psp);
  247. hPage = MyCreatePropertySheetPage(IN &m_pPageConfig->m_psp);
  248. Report(hPage != NULL);
  249. if (hPage != NULL)
  250. pCallback->AddPage(hPage);
  251. // now the Sessions page
  252. MMCPropPageCallback(INOUT &m_pPageFileAssoc->m_psp);
  253. hPage = MyCreatePropertySheetPage(IN &m_pPageFileAssoc->m_psp);
  254. Report(hPage != NULL);
  255. if (hPage != NULL)
  256. pCallback->AddPage(hPage);
  257. // finally the File Association page
  258. MMCPropPageCallback(INOUT &m_pPageSessions->m_psp);
  259. hPage = MyCreatePropertySheetPage(IN &m_pPageSessions->m_psp);
  260. Report(hPage != NULL);
  261. if (hPage != NULL)
  262. pCallback->AddPage(hPage);
  263. // add pages
  264. hr = pProvider->AddPrimaryPages(NULL, FALSE, NULL, FALSE);
  265. if (FAILED(hr))
  266. {
  267. bReturn = FALSE;
  268. goto Error;
  269. }
  270. hWnd = ::FindMMCMainWindow();
  271. _ASSERTE(hWnd != NULL);
  272. hr = pProvider->Show((LONG_PTR) hWnd, 0);
  273. if (FAILED(hr))
  274. {
  275. bReturn = FALSE;
  276. goto Error;
  277. }
  278. Error:
  279. if (pCallback)
  280. pCallback->Release();
  281. if (pProvider)
  282. pProvider->Release();
  283. // release our data object... we don't need it anymore
  284. m_spDataObject = NULL;
  285. return bReturn;
  286. }
  287. int
  288. CSFMPropertySheet::AddRef()
  289. {
  290. return ++m_nRefCount;
  291. }
  292. int
  293. CSFMPropertySheet::Release()
  294. {
  295. int nRefCount = --m_nRefCount;
  296. if (nRefCount == 0)
  297. Destroy();
  298. return nRefCount;
  299. }
  300. void
  301. CSFMPropertySheet::SetSheetWindow
  302. (
  303. HWND hSheetWindow
  304. )
  305. {
  306. if (m_hSheetWindow && !hSheetWindow)
  307. {
  308. // The Property Sheet is going away. Notify the provider so it can release
  309. // any references to the object.
  310. if (m_pSfmProvider)
  311. m_pSfmProvider->SetSfmPropSheet(NULL);
  312. }
  313. m_hSheetWindow = hSheetWindow;
  314. if (!m_hThread)
  315. {
  316. HANDLE hPseudohandle;
  317. hPseudohandle = GetCurrentThread();
  318. BOOL bRet = DuplicateHandle(GetCurrentProcess(),
  319. hPseudohandle,
  320. GetCurrentProcess(),
  321. &m_hThread,
  322. 0,
  323. FALSE,
  324. DUPLICATE_SAME_ACCESS);
  325. if (!bRet)
  326. {
  327. DWORD dwLastErr = GetLastError();
  328. }
  329. TRACE(_T("SfmProperty Sheet - Thread ID = %lx\n"), GetCurrentThreadId());
  330. }
  331. }
  332. void
  333. CSFMPropertySheet::Destroy()
  334. {
  335. m_hSheetWindow = NULL;
  336. delete this;
  337. }
  338. void
  339. CSFMPropertySheet::CancelSheet()
  340. {
  341. HWND hSheetWindow = m_hSheetWindow;
  342. if (hSheetWindow != NULL)
  343. {
  344. // this message will cause the sheet to close all the pages,
  345. // and eventually the destruction of "this"
  346. VERIFY(::PostMessage(hSheetWindow, WM_COMMAND, IDCANCEL, 0L) != 0);
  347. }
  348. // now, if we've been initialized then wait for the property sheet thread
  349. // to terminate. The property sheet provider is holding onto our dataobject
  350. // that needs to be freed up before we can continue our cleanup.
  351. if (m_hThread)
  352. {
  353. DWORD dwRet;
  354. MSG msg;
  355. while(1)
  356. {
  357. dwRet = MsgWaitForMultipleObjects(1, &m_hThread, FALSE, INFINITE, QS_ALLINPUT);
  358. if (dwRet == WAIT_OBJECT_0)
  359. return; // The event was signaled
  360. if (dwRet != WAIT_OBJECT_0 + 1)
  361. break; // Something else happened
  362. // There is one or more window message available. Dispatch them
  363. while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
  364. {
  365. TranslateMessage(&msg);
  366. DispatchMessage(&msg);
  367. if (WaitForSingleObject(m_hThread, 0) == WAIT_OBJECT_0)
  368. return; // Event is now signaled.
  369. }
  370. }
  371. }
  372. }
  373. /*!--------------------------------------------------------------------------
  374. IsNT5Machine
  375. -
  376. Author: EricDav
  377. ---------------------------------------------------------------------------*/
  378. DWORD
  379. CSFMPropertySheet::IsNT5Machine(LPCTSTR pszMachine, BOOL *pfNt4)
  380. {
  381. // Look at the HKLM\Software\Microsoft\Windows NT\CurrentVersion
  382. // CurrentVersion = REG_SZ "5.0"
  383. CString skey;
  384. DWORD dwErr = ERROR_SUCCESS;
  385. TCHAR szVersion[64];
  386. HKEY hkeyMachine, hKey;
  387. DWORD dwType = REG_SZ;
  388. DWORD dwSize = sizeof(szVersion);
  389. if (!pszMachine || !lstrlen(pszMachine))
  390. {
  391. hkeyMachine = HKEY_LOCAL_MACHINE;
  392. }
  393. else
  394. {
  395. //
  396. // Make the connection
  397. //
  398. dwErr = ::RegConnectRegistry(
  399. (LPTSTR)pszMachine, HKEY_LOCAL_MACHINE, &hkeyMachine
  400. );
  401. }
  402. if (dwErr != ERROR_SUCCESS)
  403. return dwErr;
  404. ASSERT(pfNt4);
  405. skey = c_szSoftware;
  406. skey += TEXT('\\');
  407. skey += c_szMicrosoft;
  408. skey += TEXT('\\');
  409. skey += c_szWindowsNT;
  410. skey += TEXT('\\');
  411. skey += c_szCurrentVersion;
  412. dwErr = ::RegOpenKeyEx( hkeyMachine, skey, 0, KEY_READ, & hKey ) ;
  413. if (dwErr != ERROR_SUCCESS)
  414. return dwErr;
  415. // Ok, now try to get the current version value
  416. dwErr = ::RegQueryValueEx( hKey,
  417. c_szCurrentVersion,
  418. 0,
  419. &dwType,
  420. (LPBYTE) szVersion,
  421. &dwSize ) ;
  422. if (dwErr == ERROR_SUCCESS)
  423. {
  424. *pfNt4 = ((szVersion[0] == _T('5')) && (szVersion[1] == _T('.')));
  425. }
  426. ::RegCloseKey( hKey );
  427. if (hkeyMachine != HKEY_LOCAL_MACHINE)
  428. ::RegCloseKey( hkeyMachine );
  429. return dwErr;
  430. }