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.

374 lines
10 KiB

  1. /* Copyright (c) 1995, Microsoft Corporation, all rights reserved
  2. **
  3. ** popupdlg.c
  4. ** UI helper library
  5. ** Popup dialog routines
  6. ** Listed alphabetically
  7. **
  8. ** 08/25/95 Steve Cobb
  9. */
  10. #include <nt.h> // NT declarations
  11. #include <ntrtl.h> // NT general runtime-library
  12. #include <nturtl.h> // NT user-mode runtime-library
  13. #include <windows.h> // Win32 root
  14. #include <lmerr.h> // LAN Manager errors
  15. #include <lmcons.h> // LAN Manager constants
  16. #include <stdarg.h> // To stop va_list argument warning only
  17. #include <ras.h> // RAS API definitions
  18. #include <raserror.h> // Win32 RAS error codes
  19. #include <debug.h> // Trace/assert library
  20. #include <nouiutil.h> // No-HWND utilities
  21. #include <uiutil.h> // Our public header
  22. /*----------------------------------------------------------------------------
  23. ** Error popup
  24. **----------------------------------------------------------------------------
  25. */
  26. int
  27. ErrorDlgUtil(
  28. IN HWND hwndOwner,
  29. IN DWORD dwOperation,
  30. IN DWORD dwError,
  31. IN OUT ERRORARGS* pargs,
  32. IN HINSTANCE hInstance,
  33. IN DWORD dwTitle,
  34. IN DWORD dwFormat )
  35. /* Pops up a modal error dialog centered on 'hwndOwner'. 'DwOperation' is
  36. ** the string resource ID of the string describing the operation underway
  37. ** when the error occurred. 'DwError' is the code of the system or RAS
  38. ** error that occurred. 'Pargs' is a extended formatting arguments or
  39. ** NULL if none. 'hInstance' is the application/module handle where
  40. ** string resources are located. 'DwTitle' is the string ID of the dialog
  41. ** title. 'DwFormat' is the string ID of the error format title.
  42. **
  43. ** Returns MessageBox-style code.
  44. */
  45. {
  46. TCHAR* pszUnformatted;
  47. TCHAR* pszOp;
  48. TCHAR szErrorNum[ 50 ];
  49. TCHAR* pszError;
  50. TCHAR* pszResult;
  51. TCHAR* pszNotFound;
  52. int nResult;
  53. TRACE("ErrorDlgUtil");
  54. /* A placeholder for missing strings components.
  55. */
  56. pszNotFound = TEXT("");
  57. /* Build the error number string.
  58. */
  59. if (dwError > 0x7FFFFFFF)
  60. wsprintf( szErrorNum, TEXT("0x%X"), dwError );
  61. else
  62. wsprintf( szErrorNum, TEXT("%u"), dwError );
  63. /* Build the error text string.
  64. */
  65. if (!GetErrorText( dwError, &pszError ))
  66. pszError = pszNotFound;
  67. /* Build the operation string.
  68. */
  69. pszUnformatted = PszFromId( hInstance, dwOperation );
  70. pszOp = pszNotFound;
  71. if (pszUnformatted)
  72. {
  73. FormatMessage(
  74. FORMAT_MESSAGE_FROM_STRING +
  75. FORMAT_MESSAGE_ALLOCATE_BUFFER +
  76. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  77. pszUnformatted, 0, 0, (LPTSTR )&pszOp, 1,
  78. (va_list* )((pargs) ? pargs->apszOpArgs : NULL) );
  79. Free( pszUnformatted );
  80. }
  81. /* Call MsgDlgUtil with the standard arguments plus any auxillary format
  82. ** arguments.
  83. */
  84. pszUnformatted = PszFromId( hInstance, dwFormat );
  85. pszResult = pszNotFound;
  86. if (pszUnformatted)
  87. {
  88. MSGARGS msgargs;
  89. ZeroMemory( &msgargs, sizeof(msgargs) );
  90. msgargs.dwFlags = MB_ICONEXCLAMATION + MB_OK + MB_SETFOREGROUND;
  91. msgargs.pszString = pszUnformatted;
  92. msgargs.apszArgs[ 0 ] = pszOp;
  93. msgargs.apszArgs[ 1 ] = szErrorNum;
  94. msgargs.apszArgs[ 2 ] = pszError;
  95. if (pargs)
  96. {
  97. msgargs.fStringOutput = pargs->fStringOutput;
  98. CopyMemory( &msgargs.apszArgs[ 3 ], pargs->apszAuxFmtArgs,
  99. 3 * sizeof(TCHAR) );
  100. }
  101. nResult =
  102. MsgDlgUtil(
  103. hwndOwner, 0, &msgargs, hInstance, dwTitle );
  104. Free( pszUnformatted );
  105. if (pargs && pargs->fStringOutput)
  106. pargs->pszOutput = msgargs.pszOutput;
  107. }
  108. if (pszOp != pszNotFound)
  109. LocalFree( pszOp );
  110. if (pszError != pszNotFound)
  111. LocalFree( pszError );
  112. return nResult;
  113. }
  114. BOOL
  115. GetErrorText(
  116. DWORD dwError,
  117. TCHAR** ppszError )
  118. /* Fill caller's '*ppszError' with the address of a LocalAlloc'ed heap
  119. ** block containing the error text associated with error 'dwError'. It is
  120. ** caller's responsibility to LocalFree the returned string.
  121. **
  122. ** Returns true if successful, false otherwise.
  123. */
  124. {
  125. #define MAXRASERRORLEN 256
  126. TCHAR szBuf[ MAXRASERRORLEN + 1 ];
  127. DWORD dwFlags;
  128. HANDLE hmodule;
  129. DWORD cch;
  130. /* Don't panic if the RAS API address is not loaded. Caller may be trying
  131. ** and get an error up during LoadRas.
  132. */
  133. if ((Rasapi32DllLoaded() || RasRpcDllLoaded())
  134. && g_pRasGetErrorString
  135. && g_pRasGetErrorString(
  136. (UINT )dwError, (LPTSTR )szBuf, MAXRASERRORLEN ) == 0)
  137. {
  138. /* It's a RAS error.
  139. */
  140. *ppszError = LocalAlloc( LPTR, (lstrlen( szBuf ) + 1) * sizeof(TCHAR) );
  141. if (!*ppszError)
  142. return FALSE;
  143. lstrcpy( *ppszError, szBuf );
  144. return TRUE;
  145. }
  146. /* The rest adapted from BLT's LoadSystem routine.
  147. */
  148. dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_IGNORE_INSERTS;
  149. if (dwError >= MIN_LANMAN_MESSAGE_ID && dwError <= MAX_LANMAN_MESSAGE_ID)
  150. {
  151. /* It's a net error.
  152. */
  153. dwFlags += FORMAT_MESSAGE_FROM_HMODULE;
  154. hmodule = GetModuleHandle( TEXT("NETMSG.DLL") );
  155. }
  156. else
  157. {
  158. /* It must be a system error.
  159. */
  160. dwFlags += FORMAT_MESSAGE_FROM_SYSTEM;
  161. hmodule = NULL;
  162. }
  163. /* Whistler bug: 389111 VPN connection returns unacceptable error message
  164. ** when smart card is not available
  165. */
  166. dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK;
  167. /* This is an NTSTATUS error msg.
  168. */
  169. if (NT_ERROR(dwError))
  170. {
  171. dwError = RtlNtStatusToDosError( dwError );
  172. }
  173. cch = FormatMessage(
  174. dwFlags, hmodule, dwError, 0, (LPTSTR )ppszError, 1, NULL );
  175. /* FormatMessage failed so we are going to get a generic one from RAS.
  176. */
  177. if (!cch || !*ppszError)
  178. {
  179. Free0( *ppszError );
  180. dwError = ERROR_UNKNOWN;
  181. if ((Rasapi32DllLoaded() || RasRpcDllLoaded())
  182. && g_pRasGetErrorString
  183. && g_pRasGetErrorString(
  184. (UINT )dwError, (LPTSTR )szBuf, MAXRASERRORLEN ) == 0)
  185. {
  186. *ppszError = LocalAlloc( LPTR, (lstrlen( szBuf ) + 1) *
  187. sizeof(TCHAR) );
  188. if (!*ppszError)
  189. return FALSE;
  190. lstrcpy( *ppszError, szBuf );
  191. return TRUE;
  192. }
  193. }
  194. return (cch > 0);
  195. }
  196. /*----------------------------------------------------------------------------
  197. ** Message popup
  198. **----------------------------------------------------------------------------
  199. */
  200. int
  201. MsgDlgUtil(
  202. IN HWND hwndOwner,
  203. IN DWORD dwMsg,
  204. IN OUT MSGARGS* pargs,
  205. IN HINSTANCE hInstance,
  206. IN DWORD dwTitle )
  207. /* Pops up a message dialog centered on 'hwndOwner'. 'DwMsg' is the
  208. ** string resource ID of the message text. 'Pargs' is a extended
  209. ** formatting arguments or NULL if none. 'hInstance' is the
  210. ** application/module handle where string resources are located.
  211. ** 'DwTitle' is the string ID of the dialog title.
  212. **
  213. ** Returns MessageBox-style code.
  214. */
  215. {
  216. TCHAR* pszUnformatted;
  217. TCHAR* pszResult;
  218. TCHAR* pszNotFound;
  219. int nResult;
  220. TRACE("MsgDlgUtil");
  221. /* A placeholder for missing strings components.
  222. */
  223. pszNotFound = TEXT("");
  224. /* Build the message string.
  225. */
  226. pszResult = pszNotFound;
  227. if (pargs && pargs->pszString)
  228. {
  229. FormatMessage(
  230. FORMAT_MESSAGE_FROM_STRING +
  231. FORMAT_MESSAGE_ALLOCATE_BUFFER +
  232. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  233. pargs->pszString, 0, 0, (LPTSTR )&pszResult, 1,
  234. (va_list* )pargs->apszArgs );
  235. }
  236. else
  237. {
  238. pszUnformatted = PszFromId( hInstance, dwMsg );
  239. if (pszUnformatted)
  240. {
  241. FormatMessage(
  242. FORMAT_MESSAGE_FROM_STRING +
  243. FORMAT_MESSAGE_ALLOCATE_BUFFER +
  244. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  245. pszUnformatted, 0, 0, (LPTSTR )&pszResult, 1,
  246. (va_list* )((pargs) ? pargs->apszArgs : NULL) );
  247. Free( pszUnformatted );
  248. }
  249. }
  250. if (!pargs || !pargs->fStringOutput)
  251. {
  252. TCHAR* pszTitle;
  253. DWORD dwFlags;
  254. HHOOK hhook;
  255. if (pargs && pargs->dwFlags != 0)
  256. dwFlags = pargs->dwFlags;
  257. else
  258. dwFlags = MB_ICONINFORMATION + MB_OK + MB_SETFOREGROUND;
  259. pszTitle = PszFromId( hInstance, dwTitle );
  260. if (hwndOwner)
  261. {
  262. /* Install hook that will get the message box centered on the
  263. ** owner window.
  264. */
  265. hhook = SetWindowsHookEx( WH_CALLWNDPROC,
  266. CenterDlgOnOwnerCallWndProc,
  267. hInstance, GetCurrentThreadId() );
  268. }
  269. else
  270. hhook = NULL;
  271. if (pszResult)
  272. {
  273. nResult = MessageBox( hwndOwner, pszResult, pszTitle, dwFlags );
  274. }
  275. if (hhook)
  276. UnhookWindowsHookEx( hhook );
  277. Free0( pszTitle );
  278. if (pszResult != pszNotFound)
  279. LocalFree( pszResult );
  280. }
  281. else
  282. {
  283. /* Caller wants the string without doing the popup.
  284. */
  285. pargs->pszOutput = (pszResult != pszNotFound) ? pszResult : NULL;
  286. nResult = IDOK;
  287. }
  288. return nResult;
  289. }
  290. LRESULT CALLBACK
  291. CenterDlgOnOwnerCallWndProc(
  292. int code,
  293. WPARAM wparam,
  294. LPARAM lparam )
  295. /* Standard Win32 CallWndProc hook callback that looks for the next dialog
  296. ** started and centers it on it's owner window.
  297. */
  298. {
  299. /* Arrive here when any window procedure associated with our thread is
  300. ** called.
  301. */
  302. if (!wparam)
  303. {
  304. CWPSTRUCT* p = (CWPSTRUCT* )lparam;
  305. /* The message is from outside our process. Look for the MessageBox
  306. ** dialog initialization message and take that opportunity to center
  307. ** the dialog on it's owner's window.
  308. */
  309. if (p->message == WM_INITDIALOG)
  310. CenterWindow( p->hwnd, GetParent( p->hwnd ) );
  311. }
  312. return 0;
  313. }