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.

883 lines
18 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. //
  4. // the following is not in the SDK
  5. //
  6. #include <pshpack2.h>
  7. #include <poppack.h>
  8. #include <winuserp.h>
  9. //
  10. // When Winnt32.exe is launched over a network, these two parameters have valid
  11. // values and need to be taken into consideration before displaying any dialog box
  12. //
  13. extern HWND Winnt32Dlg;
  14. extern HANDLE WinNT32StubEvent;
  15. PCTSTR
  16. GetStringResource (
  17. IN UINT Id
  18. )
  19. {
  20. LONG rc;
  21. PCTSTR MsgBuf;
  22. if (HIWORD (Id)) {
  23. // From string
  24. rc = FormatMessage (
  25. FORMAT_MESSAGE_ALLOCATE_BUFFER|
  26. FORMAT_MESSAGE_ARGUMENT_ARRAY|
  27. FORMAT_MESSAGE_FROM_STRING,
  28. UIntToPtr( Id ),
  29. 0,
  30. 0,
  31. (PVOID) &MsgBuf,
  32. 0,
  33. NULL
  34. );
  35. }
  36. else {
  37. // From resource
  38. rc = FormatMessage (
  39. FORMAT_MESSAGE_ALLOCATE_BUFFER|
  40. FORMAT_MESSAGE_ARGUMENT_ARRAY|
  41. FORMAT_MESSAGE_FROM_HMODULE,
  42. (PVOID) hInst,
  43. (DWORD) Id,
  44. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  45. (LPVOID) &MsgBuf,
  46. 0,
  47. NULL
  48. );
  49. }
  50. if (rc == 0) {
  51. return NULL;
  52. }
  53. return MsgBuf;
  54. }
  55. VOID
  56. FreeStringResource (
  57. IN PCTSTR String
  58. )
  59. {
  60. if (String) {
  61. LocalFree ((HLOCAL) String);
  62. }
  63. }
  64. VOID
  65. SaveTextForSMS(
  66. IN PCTSTR Buffer
  67. )
  68. {
  69. CHAR AnsiBuffer[5000];
  70. if(LastMessage) {
  71. FREE( LastMessage );
  72. }
  73. #ifdef UNICODE
  74. WideCharToMultiByte(
  75. CP_ACP,
  76. 0,
  77. Buffer,
  78. -1,
  79. AnsiBuffer,
  80. sizeof(AnsiBuffer),
  81. NULL,
  82. NULL
  83. );
  84. if(LastMessage = MALLOC(strlen(AnsiBuffer)+1)) {
  85. strcpy( LastMessage, AnsiBuffer);
  86. }
  87. #else
  88. LastMessage = DupString( Buffer );
  89. #endif
  90. }
  91. VOID
  92. SaveMessageForSMS(
  93. IN DWORD MessageId,
  94. ...
  95. )
  96. {
  97. va_list arglist;
  98. TCHAR Buffer[5000];
  99. va_start(arglist,MessageId);
  100. FormatMessage(
  101. FORMAT_MESSAGE_FROM_HMODULE,
  102. hInst,
  103. MessageId,
  104. 0,
  105. Buffer,
  106. sizeof(Buffer) / sizeof(TCHAR),
  107. &arglist
  108. );
  109. SaveTextForSMS(Buffer);
  110. va_end(arglist);
  111. }
  112. int
  113. MessageBoxFromMessageV(
  114. IN HWND Window,
  115. IN DWORD MessageId,
  116. IN BOOL SystemMessage,
  117. IN DWORD CaptionStringId,
  118. IN UINT Style,
  119. IN va_list *Args
  120. )
  121. {
  122. TCHAR Caption[512];
  123. TCHAR Buffer[5000];
  124. HWND Parent;
  125. if(!LoadString(hInst,CaptionStringId,Caption,sizeof(Caption)/sizeof(TCHAR))) {
  126. Caption[0] = 0;
  127. }
  128. FormatMessage(
  129. SystemMessage ? FORMAT_MESSAGE_FROM_SYSTEM : FORMAT_MESSAGE_FROM_HMODULE,
  130. hInst,
  131. MessageId,
  132. 0,
  133. Buffer,
  134. sizeof(Buffer) / sizeof(TCHAR),
  135. Args
  136. );
  137. SaveTextForSMS(Buffer);
  138. //
  139. // In batch mode, we don't want to wait on the user.
  140. //
  141. if(BatchMode) {
  142. if( Style & MB_YESNO ) {
  143. return( IDYES );
  144. } else {
  145. return( IDOK );
  146. }
  147. }
  148. //
  149. // Force ourselves into the foreground manually to guarantee that we get
  150. // a chance to set our palette. Otherwise the message box gets the
  151. // palette messages and color in our background bitmap can get hosed.
  152. // We assume the parent is a wizard page.
  153. //
  154. if(Window && IsWindow(Window)) {
  155. Parent = GetParent(Window);
  156. if(!Parent) {
  157. Parent = Window;
  158. }
  159. } else {
  160. Parent = NULL;
  161. }
  162. SetForegroundWindow(Parent);
  163. //
  164. // If we're just checking upgrades, and we're on NT,
  165. // then throw this message into the compatibility list.
  166. //
  167. if( CheckUpgradeOnly && ISNT() ) {
  168. PCOMPATIBILITY_DATA CompData;
  169. CompData = (PCOMPATIBILITY_DATA) MALLOC( sizeof(COMPATIBILITY_DATA) );
  170. if (CompData == NULL) {
  171. return 0;
  172. }
  173. ZeroMemory( CompData, sizeof(COMPATIBILITY_DATA) );
  174. CompData->Description = DupString( Buffer );
  175. CompData->Flags = COMPFLAG_STOPINSTALL;
  176. if( !CompatibilityData.Flink ) {
  177. InitializeListHead( &CompatibilityData );
  178. }
  179. InsertTailList( &CompatibilityData, &CompData->ListEntry );
  180. CompatibilityCount++;
  181. if( Style & MB_YESNO ) {
  182. return( IDYES );
  183. } else {
  184. return( IDOK );
  185. }
  186. }
  187. //
  188. // always make sure the window is visible
  189. //
  190. if (Window && !IsWindowVisible (Window)) {
  191. //
  192. // if this window is the wizard handle or one of its pages
  193. // then use a special message to restore it
  194. //
  195. if (WizardHandle &&
  196. (WizardHandle == Window || IsChild (WizardHandle, Window))
  197. ) {
  198. SendMessage(WizardHandle, WMX_BBTEXT, (WPARAM)FALSE, 0);
  199. } else {
  200. //
  201. // the window is one of the billboard windows;
  202. // just leave it alone or weird things may happen
  203. //
  204. }
  205. }
  206. return(MessageBox(Window,Buffer,Caption,Style));
  207. }
  208. int
  209. MessageBoxFromMessage(
  210. IN HWND Window,
  211. IN DWORD MessageId,
  212. IN BOOL SystemMessage,
  213. IN DWORD CaptionStringId,
  214. IN UINT Style,
  215. ...
  216. )
  217. {
  218. va_list arglist;
  219. int i;
  220. //
  221. // before displaying any dialog, make sure Winnt32.exe wait dialog is gone
  222. //
  223. if (Winnt32Dlg) {
  224. DestroyWindow (Winnt32Dlg);
  225. Winnt32Dlg = NULL;
  226. }
  227. if (WinNT32StubEvent) {
  228. SetEvent (WinNT32StubEvent);
  229. WinNT32StubEvent = NULL;
  230. }
  231. va_start(arglist,Style);
  232. i = MessageBoxFromMessageV(Window,MessageId,SystemMessage,CaptionStringId,Style,&arglist);
  233. va_end(arglist);
  234. return(i);
  235. }
  236. int
  237. MessageBoxFromMessageWithSystem(
  238. IN HWND Window,
  239. IN DWORD MessageId,
  240. IN DWORD CaptionStringId,
  241. IN UINT Style,
  242. IN HMODULE hMod
  243. )
  244. {
  245. TCHAR Caption[512];
  246. TCHAR Buffer[5000];
  247. HWND Parent;
  248. DWORD i;
  249. if(!LoadString(hInst,CaptionStringId,Caption,sizeof(Caption)/sizeof(TCHAR))) {
  250. Caption[0] = 0;
  251. }
  252. i = FormatMessage(
  253. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,
  254. hMod,
  255. MessageId,
  256. 0,
  257. Buffer,
  258. sizeof(Buffer) / sizeof(TCHAR),
  259. NULL
  260. );
  261. if (i == 0) {
  262. return -1;
  263. }
  264. SaveTextForSMS(Buffer);
  265. //
  266. // In batch mode, we don't want to wait on the user.
  267. //
  268. if(BatchMode) {
  269. if( Style & MB_YESNO ) {
  270. return( IDYES );
  271. } else {
  272. return( IDOK );
  273. }
  274. }
  275. //
  276. // Force ourselves into the foreground manually to guarantee that we get
  277. // a chance to set our palette. Otherwise the message box gets the
  278. // palette messages and color in our background bitmap can get hosed.
  279. // We assume the parent is a wizard page.
  280. //
  281. if(Window && IsWindow(Window)) {
  282. Parent = GetParent(Window);
  283. if(!Parent) {
  284. Parent = Window;
  285. }
  286. } else {
  287. Parent = NULL;
  288. }
  289. SetForegroundWindow(Parent);
  290. return(MessageBox(Window,Buffer,Caption,Style));
  291. }
  292. int
  293. MessageBoxFromMessageAndSystemError(
  294. IN HWND Window,
  295. IN DWORD MessageId,
  296. IN DWORD SystemMessageId,
  297. IN DWORD CaptionStringId,
  298. IN UINT Style,
  299. ...
  300. )
  301. {
  302. va_list arglist;
  303. TCHAR Caption[500];
  304. TCHAR Buffer1[2000];
  305. TCHAR Buffer2[1000];
  306. int i;
  307. //
  308. // Fetch the non-system part. The arguments are for that part of the
  309. // message -- the system part has no inserts.
  310. //
  311. va_start(arglist,Style);
  312. FormatMessage(
  313. FORMAT_MESSAGE_FROM_HMODULE,
  314. hInst,
  315. MessageId,
  316. 0,
  317. Buffer1,
  318. sizeof(Buffer1) / sizeof(TCHAR),
  319. &arglist
  320. );
  321. va_end(arglist);
  322. //
  323. // Now fetch the system part.
  324. //
  325. i = (int)FormatMessage(
  326. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  327. NULL,
  328. SystemMessageId,
  329. 0,
  330. Buffer2,
  331. sizeof(Buffer2) / sizeof(TCHAR),
  332. NULL
  333. );
  334. if(!i) {
  335. FormatMessage(
  336. FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  337. hInst,
  338. MSG_UNKNOWN_SYSTEM_ERROR,
  339. 0,
  340. Buffer2,
  341. sizeof(Buffer2) / sizeof(TCHAR),
  342. (va_list *)&SystemMessageId
  343. );
  344. }
  345. //
  346. // Now display the message, which is made up of two parts that get
  347. // inserted into MSG_ERROR_WITH_SYSTEM_ERROR.
  348. //
  349. i = MessageBoxFromMessage(
  350. Window,
  351. MSG_ERROR_WITH_SYSTEM_ERROR,
  352. FALSE,
  353. CaptionStringId,
  354. Style,
  355. Buffer1,
  356. Buffer2
  357. );
  358. return(i);
  359. }
  360. HPALETTE
  361. CreateDIBPalette(
  362. IN LPBITMAPINFO BitmapInfo,
  363. OUT int *ColorCount
  364. )
  365. /*++
  366. Routine Description:
  367. Arguments:
  368. Return Value:
  369. --*/
  370. {
  371. LPBITMAPINFOHEADER BitmapInfoHeader;
  372. LPLOGPALETTE LogicalPalette;
  373. HPALETTE Palette;
  374. int i;
  375. DWORD d;
  376. BitmapInfoHeader = (LPBITMAPINFOHEADER)BitmapInfo;
  377. //
  378. // No palette needed for >= 16 bpp
  379. //
  380. *ColorCount = (BitmapInfoHeader->biBitCount <= 8)
  381. ? (1 << BitmapInfoHeader->biBitCount)
  382. : 0;
  383. if(*ColorCount) {
  384. LogicalPalette = MALLOC(sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * (*ColorCount)));
  385. if(!LogicalPalette) {
  386. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  387. return(NULL);
  388. }
  389. LogicalPalette->palVersion = 0x300;
  390. LogicalPalette->palNumEntries = (WORD)*ColorCount;
  391. for(i=0; i<*ColorCount; i++) {
  392. LogicalPalette->palPalEntry[i].peRed = BitmapInfo->bmiColors[i].rgbRed;
  393. LogicalPalette->palPalEntry[i].peGreen = BitmapInfo->bmiColors[i].rgbGreen;
  394. LogicalPalette->palPalEntry[i].peBlue = BitmapInfo->bmiColors[i].rgbBlue;
  395. LogicalPalette->palPalEntry[i].peFlags = 0;
  396. }
  397. Palette = CreatePalette(LogicalPalette);
  398. d = GetLastError();
  399. FREE(LogicalPalette);
  400. SetLastError(d);
  401. } else {
  402. Palette = NULL;
  403. }
  404. return(Palette);
  405. }
  406. HBITMAP
  407. LoadResourceBitmap(
  408. IN HINSTANCE hInst,
  409. IN LPCTSTR Id,
  410. OUT HPALETTE *Palette
  411. )
  412. /*++
  413. Routine Description:
  414. Bitmaps in resources are stored as DIBs. When fetched via LoadBitmap()
  415. they are converted to DDBs and a color conversion takes place based on
  416. whatever logical palette happens to be currently selected into whatever
  417. DC gets used internally for the conversion.
  418. This routine fetches the color data from the DIB in the resources and
  419. ensures that the DIB is converted into a DDB using accurate color data.
  420. It is essentially a color-accurate replacement for LoadBitmap().
  421. Arguments:
  422. hInst - supplies instance handle for module containing the bitmap resource.
  423. Id - supplies the id of the bitmap resource.
  424. Palette - if successful, receives a handle to a palette for the bitmap.
  425. Return Value:
  426. If successful, handle to the loaded bitmap (DIB).
  427. If not, NULL is returned. Check GetLastError().
  428. --*/
  429. {
  430. DWORD d;
  431. BOOL b;
  432. HRSRC BlockHandle;
  433. HGLOBAL MemoryHandle;
  434. BITMAPINFOHEADER *BitmapInfoHeader;
  435. HDC hdc;
  436. int ColorCount;
  437. HBITMAP Bitmap;
  438. HPALETTE PreviousPalette;
  439. Bitmap = NULL;
  440. BlockHandle = FindResource(hInst,Id,RT_BITMAP);
  441. if(!BlockHandle) {
  442. d = GetLastError();
  443. goto c0;
  444. }
  445. MemoryHandle = LoadResource(hInst,BlockHandle);
  446. if(!MemoryHandle) {
  447. d = GetLastError();
  448. goto c0;
  449. }
  450. BitmapInfoHeader = LockResource(MemoryHandle);
  451. if(!BitmapInfoHeader) {
  452. d = GetLastError();
  453. goto c1;
  454. }
  455. hdc = GetDC(NULL);
  456. if(!hdc) {
  457. d = GetLastError();
  458. goto c2;
  459. }
  460. #if 0 // steveow - fix palette problem
  461. if(*Palette = CreateDIBPalette((BITMAPINFO *)BitmapInfoHeader,&ColorCount)) {
  462. PreviousPalette = SelectPalette(hdc,*Palette,FALSE);
  463. RealizePalette(hdc);
  464. } else {
  465. PreviousPalette = NULL;
  466. }
  467. #else
  468. ColorCount = 16;
  469. PreviousPalette = NULL;
  470. #endif
  471. //
  472. // This routine creates a DDB from the DIB (the name is confusing).
  473. //
  474. Bitmap = CreateDIBitmap(
  475. hdc,
  476. BitmapInfoHeader,
  477. CBM_INIT,
  478. (LPBYTE)BitmapInfoHeader + BitmapInfoHeader->biSize + (ColorCount * sizeof(RGBQUAD)),
  479. (BITMAPINFO *)BitmapInfoHeader,
  480. DIB_RGB_COLORS
  481. );
  482. if(!Bitmap) {
  483. d = GetLastError();
  484. goto c3;
  485. }
  486. c3:
  487. if(PreviousPalette) {
  488. SelectObject(hdc,PreviousPalette);
  489. }
  490. if(!Bitmap) {
  491. DeleteObject(*Palette);
  492. *Palette = NULL;
  493. }
  494. ReleaseDC(NULL,hdc);
  495. c2:
  496. UnlockResource(MemoryHandle);
  497. c1:
  498. FreeResource(MemoryHandle);
  499. c0:
  500. if(!Bitmap) {
  501. SetLastError(d);
  502. }
  503. return(Bitmap);
  504. }
  505. BOOL
  506. GetBitmapDataAndPalette(
  507. IN HINSTANCE hInst,
  508. IN LPCTSTR Id,
  509. OUT HPALETTE *Palette,
  510. OUT PUINT ColorCount,
  511. OUT CONST BITMAPINFOHEADER **BitmapData
  512. )
  513. /*++
  514. Routine Description:
  515. Retreives device-independent bitmap data and a color table from a
  516. bitmap in a resource.
  517. Arguments:
  518. hInst - supplies instance handle for module containing the bitmap resource.
  519. Id - supplies the id of the bitmap resource.
  520. Palette - if successful, receives a handle to a palette for the bitmap.
  521. ColorCount - if successful, receives the number of entries in the
  522. palette for the bitmap.
  523. BitmapData - if successful, receives a pointer to the bitmap info
  524. header structure in the resources. This is in read-only memory
  525. so the caller should not try to modify it.
  526. Return Value:
  527. If successful, handle to the loaded bitmap (DIB).
  528. If not, NULL is returned. Check GetLastError().
  529. --*/
  530. {
  531. HRSRC BlockHandle;
  532. HGLOBAL MemoryHandle;
  533. //
  534. // None of FindResource(), LoadResource(), or LockResource()
  535. // need to have cleanup routines called in Win32.
  536. //
  537. BlockHandle = FindResource(hInst,Id,RT_BITMAP);
  538. if(!BlockHandle) {
  539. return(FALSE);
  540. }
  541. MemoryHandle = LoadResource(hInst,BlockHandle);
  542. if(!MemoryHandle) {
  543. return(FALSE);
  544. }
  545. *BitmapData = LockResource(MemoryHandle);
  546. if(*BitmapData == NULL) {
  547. return(FALSE);
  548. }
  549. *Palette = CreateDIBPalette((LPBITMAPINFO)*BitmapData,ColorCount);
  550. return(TRUE);
  551. }
  552. PVOID
  553. FindControlInDialog(
  554. IN PVOID Template,
  555. IN UINT ControlId
  556. )
  557. {
  558. PVOID p;
  559. DLGTEMPLATE *pTemplate;
  560. DLGTEMPLATE2 *pTemplate2;
  561. DLGITEMTEMPLATE *pItem;
  562. DLGITEMTEMPLATE2 *pItem2;
  563. WORD ItemCount;
  564. DWORD Style;
  565. WORD i;
  566. BOOL bDialogEx;
  567. if (!Template) // validate
  568. return NULL;
  569. p = Template;
  570. //
  571. // Skip fixed part of template
  572. //
  573. if(((DLGTEMPLATE2 *)p)->wSignature == 0xffff) {
  574. pTemplate2 = p;
  575. ItemCount = pTemplate2->cDlgItems;
  576. Style = pTemplate2->style;
  577. p = pTemplate2 + 1;
  578. bDialogEx = TRUE;
  579. } else {
  580. pTemplate = p;
  581. ItemCount = pTemplate->cdit;
  582. Style = pTemplate->style;
  583. p = pTemplate + 1;
  584. bDialogEx = FALSE;
  585. }
  586. //
  587. // Skip menu. First word=0 means no menu
  588. // First word=0xffff means one more word follows
  589. // Else it's a nul-terminated string
  590. //
  591. switch(*(WORD *)p) {
  592. case 0xffff:
  593. p = (WORD *)p + 2;
  594. break;
  595. case 0:
  596. p = (WORD *)p + 1;
  597. break;
  598. default:
  599. p = (PWCHAR)p + lstrlenW(p) + 1;
  600. break;
  601. }
  602. //
  603. // Skip class, similar to menu
  604. //
  605. switch(*(WORD *)p) {
  606. case 0xffff:
  607. p = (WORD *)p + 2;
  608. break;
  609. case 0:
  610. p = (WORD *)p + 1;
  611. break;
  612. default:
  613. p = (PWCHAR)p + lstrlenW(p) + 1;
  614. break;
  615. }
  616. //
  617. // Skip title
  618. //
  619. p = (PWCHAR)p + lstrlenW(p) + 1;
  620. if(Style & DS_SETFONT) {
  621. //
  622. // Skip point size and typeface name
  623. //
  624. p = (WORD *)p + 1;
  625. if (bDialogEx)
  626. {
  627. // Skip weight, italic, and charset.
  628. p = (WORD *)p + 1;
  629. p = (BYTE *)p + 1;
  630. p = (BYTE *)p + 1;
  631. }
  632. p = (PWCHAR)p + lstrlenW(p) + 1;
  633. }
  634. //
  635. // Now we have a pointer to the first item in the dialog
  636. //
  637. for(i=0; i<ItemCount; i++) {
  638. //
  639. // Align to next DWORD boundary
  640. //
  641. p = (PVOID)(((ULONG_PTR)p + sizeof(DWORD) - 1) & (~((ULONG_PTR)sizeof(DWORD) - 1)));
  642. if (bDialogEx)
  643. {
  644. pItem2 = p;
  645. if(pItem2->dwID == (WORD)ControlId) {
  646. break;
  647. }
  648. //
  649. // Skip to next item in dialog.
  650. // First is class, which is either 0xffff plus one more word,
  651. // or a unicode string. After that is text/title.
  652. //
  653. p = pItem2 + 1;
  654. }
  655. else
  656. {
  657. pItem = p;
  658. if(pItem->id == (WORD)ControlId) {
  659. break;
  660. }
  661. //
  662. // Skip to next item in dialog.
  663. // First is class, which is either 0xffff plus one more word,
  664. // or a unicode string. After that is text/title.
  665. //
  666. p = pItem + 1;
  667. }
  668. if(*(WORD *)p == 0xffff) {
  669. p = (WORD *)p + 2;
  670. } else {
  671. p = (PWCHAR)p + lstrlenW(p) + 1;
  672. }
  673. if(*(WORD *)p == 0xffff) {
  674. p = (WORD *)p + 2;
  675. } else {
  676. p = (PWCHAR)p + lstrlenW(p) + 1;
  677. }
  678. //
  679. // Skip creation data.
  680. //
  681. p = (PUCHAR)p + *(WORD *)p;
  682. p = (WORD *)p + 1;
  683. }
  684. if(i == ItemCount) {
  685. p = NULL;
  686. }
  687. return(p);
  688. }
  689. UINT
  690. GetYPositionOfDialogItem(
  691. IN LPCTSTR Dialog,
  692. IN UINT ControlId
  693. )
  694. {
  695. HRSRC hRsrc;
  696. PVOID p;
  697. HGLOBAL hGlobal;
  698. PVOID pItem;
  699. UINT i;
  700. i = 0;
  701. if(hRsrc = FindResource(hInst,Dialog,RT_DIALOG)) {
  702. if(hGlobal = LoadResource(hInst,hRsrc)) {
  703. if(p = LockResource(hGlobal)) {
  704. if(pItem = FindControlInDialog(p,ControlId)) {
  705. if(((DLGTEMPLATE2 *)p)->wSignature == 0xffff) {
  706. i = ((DLGITEMTEMPLATE2*)pItem)->y;
  707. }
  708. else
  709. {
  710. i = ((DLGITEMTEMPLATE*)pItem)->y;
  711. }
  712. }
  713. UnlockResource(hGlobal);
  714. }
  715. FreeResource(hGlobal);
  716. }
  717. }
  718. return(i);
  719. }