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.

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