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.

1179 lines
36 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. group32.c
  5. Abstract:
  6. This module contains routines for reading/writing 32-bit Windows/NT
  7. groups that are stored in the registry.
  8. Author:
  9. Steve Wood (stevewo) 22-Feb-1993
  10. Revision History:
  11. --*/
  12. #include "advapi.h"
  13. #include <stdio.h>
  14. #include <winbasep.h>
  15. #include "win31io.h"
  16. #define BMR_ICON 1
  17. #define BMR_DEVDEP 0
  18. #define ROUND_UP( X, A ) (((ULONG_PTR)(X) + (A) - 1) & ~((A) - 1))
  19. #define PAGE_SIZE 4096
  20. #define PAGE_NUMBER( A ) ((DWORD)(A) / PAGE_SIZE)
  21. typedef int (WINAPI *PGETSYSTEMMETRICS)(
  22. int nIndex
  23. );
  24. PGETSYSTEMMETRICS lpGetSystemMetrics;
  25. ULONG
  26. QueryNumberOfPersonalGroupNames(
  27. HANDLE CurrentUser,
  28. PHANDLE GroupNamesKey,
  29. PHANDLE SettingsKey
  30. )
  31. {
  32. NTSTATUS Status;
  33. UNICODE_STRING KeyName, ValueName;
  34. OBJECT_ATTRIBUTES ObjectAttributes;
  35. WCHAR ValueNameBuffer[ 16 ];
  36. KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  37. ULONG ResultLength, NumberOfPersonalGroups;
  38. RtlInitUnicodeString( &KeyName, L"SoftWare\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager\\UNICODE Groups" );
  39. InitializeObjectAttributes( &ObjectAttributes,
  40. &KeyName,
  41. OBJ_CASE_INSENSITIVE,
  42. CurrentUser,
  43. NULL
  44. );
  45. Status = NtOpenKey( GroupNamesKey,
  46. STANDARD_RIGHTS_WRITE |
  47. KEY_QUERY_VALUE |
  48. KEY_ENUMERATE_SUB_KEYS |
  49. KEY_SET_VALUE |
  50. KEY_CREATE_SUB_KEY,
  51. &ObjectAttributes
  52. );
  53. if (!NT_SUCCESS( Status )) {
  54. BaseSetLastNTError( Status );
  55. return 0;
  56. }
  57. RtlInitUnicodeString( &KeyName, L"SoftWare\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager\\Settings" );
  58. InitializeObjectAttributes( &ObjectAttributes,
  59. &KeyName,
  60. OBJ_CASE_INSENSITIVE,
  61. CurrentUser,
  62. NULL
  63. );
  64. Status = NtOpenKey( SettingsKey,
  65. STANDARD_RIGHTS_WRITE |
  66. KEY_QUERY_VALUE |
  67. KEY_ENUMERATE_SUB_KEYS |
  68. KEY_SET_VALUE |
  69. KEY_CREATE_SUB_KEY,
  70. &ObjectAttributes
  71. );
  72. if (!NT_SUCCESS( Status )) {
  73. BaseSetLastNTError( Status );
  74. NtClose( *GroupNamesKey );
  75. return 0;
  76. }
  77. for (NumberOfPersonalGroups=1; ; NumberOfPersonalGroups++) {
  78. swprintf( ValueNameBuffer, L"Group%d", NumberOfPersonalGroups );
  79. RtlInitUnicodeString( &ValueName, ValueNameBuffer );
  80. Status = NtQueryValueKey( *GroupNamesKey,
  81. &ValueName,
  82. KeyValuePartialInformation,
  83. (PVOID)&KeyValueInformation,
  84. sizeof( KeyValueInformation ),
  85. &ResultLength
  86. );
  87. if (Status == STATUS_BUFFER_OVERFLOW) {
  88. Status = STATUS_SUCCESS;
  89. }
  90. if (!NT_SUCCESS( Status ) ||
  91. KeyValueInformation.Type != REG_SZ
  92. ) {
  93. break;
  94. }
  95. }
  96. return NumberOfPersonalGroups - 1;
  97. }
  98. BOOL
  99. NewPersonalGroupName(
  100. HANDLE GroupNamesKey,
  101. PWSTR GroupName,
  102. ULONG GroupNumber
  103. )
  104. {
  105. NTSTATUS Status;
  106. UNICODE_STRING ValueName;
  107. WCHAR ValueNameBuffer[ 16 ];
  108. if (GroupNumber >= CGROUPSMAX) {
  109. SetLastError( ERROR_TOO_MANY_NAMES );
  110. return FALSE;
  111. }
  112. swprintf( ValueNameBuffer, L"Group%d", GroupNumber );
  113. RtlInitUnicodeString( &ValueName, ValueNameBuffer );
  114. Status = NtSetValueKey( GroupNamesKey,
  115. &ValueName,
  116. 0,
  117. REG_SZ,
  118. GroupName,
  119. (wcslen( GroupName ) + 1) * sizeof( WCHAR )
  120. );
  121. if (!NT_SUCCESS( Status )) {
  122. BaseSetLastNTError( Status );
  123. return FALSE;
  124. }
  125. else {
  126. return TRUE;
  127. }
  128. }
  129. BOOL
  130. DoesExistGroup(
  131. HANDLE GroupsKey,
  132. PWSTR GroupName
  133. )
  134. {
  135. NTSTATUS Status;
  136. UNICODE_STRING KeyName, ValueName;
  137. HANDLE Key;
  138. OBJECT_ATTRIBUTES ObjectAttributes;
  139. KEY_VALUE_FULL_INFORMATION KeyValueInformation;
  140. ULONG ResultLength;
  141. RtlInitUnicodeString( &KeyName, GroupName );
  142. InitializeObjectAttributes( &ObjectAttributes,
  143. &KeyName,
  144. OBJ_CASE_INSENSITIVE,
  145. GroupsKey,
  146. NULL
  147. );
  148. Status = NtOpenKey( &Key,
  149. GENERIC_READ,
  150. &ObjectAttributes
  151. );
  152. if (!NT_SUCCESS( Status )) {
  153. BaseSetLastNTError( Status );
  154. return FALSE;
  155. }
  156. RtlInitUnicodeString( &ValueName, L"" );
  157. Status = NtQueryValueKey( Key,
  158. &ValueName,
  159. KeyValueFullInformation,
  160. &KeyValueInformation,
  161. sizeof( KeyValueInformation ),
  162. &ResultLength
  163. );
  164. NtClose( Key );
  165. if (!NT_SUCCESS( Status ) && Status != STATUS_BUFFER_OVERFLOW) {
  166. BaseSetLastNTError( Status );
  167. return FALSE;
  168. }
  169. else
  170. if (KeyValueInformation.Type != REG_BINARY ||
  171. KeyValueInformation.DataLength > 0xFFFF
  172. ) {
  173. return FALSE;
  174. }
  175. else {
  176. return TRUE;
  177. }
  178. }
  179. PGROUP_DEF
  180. LoadGroup(
  181. HANDLE GroupsKey,
  182. PWSTR GroupName
  183. )
  184. {
  185. PGROUP_DEF Group;
  186. NTSTATUS Status;
  187. UNICODE_STRING KeyName, ValueName;
  188. HANDLE Key;
  189. OBJECT_ATTRIBUTES ObjectAttributes;
  190. PVOID Base;
  191. KEY_VALUE_FULL_INFORMATION KeyValueInformation;
  192. ULONG ResultLength;
  193. RtlInitUnicodeString( &KeyName, GroupName );
  194. InitializeObjectAttributes( &ObjectAttributes,
  195. &KeyName,
  196. OBJ_CASE_INSENSITIVE,
  197. GroupsKey,
  198. NULL
  199. );
  200. Status = NtOpenKey( &Key,
  201. GENERIC_READ,
  202. &ObjectAttributes
  203. );
  204. if (!NT_SUCCESS( Status )) {
  205. BaseSetLastNTError( Status );
  206. return NULL;
  207. }
  208. RtlInitUnicodeString( &ValueName, L"" );
  209. Status = NtQueryValueKey( Key,
  210. &ValueName,
  211. KeyValueFullInformation,
  212. &KeyValueInformation,
  213. sizeof( KeyValueInformation ),
  214. &ResultLength
  215. );
  216. if (!NT_SUCCESS( Status )) {
  217. if (Status == STATUS_BUFFER_OVERFLOW) {
  218. Status = STATUS_SUCCESS;
  219. }
  220. else {
  221. NtClose( Key );
  222. BaseSetLastNTError( Status );
  223. return NULL;
  224. }
  225. }
  226. if (KeyValueInformation.Type != REG_BINARY ||
  227. KeyValueInformation.DataLength > 0xFFFF
  228. ) {
  229. NtClose( Key );
  230. return NULL;
  231. }
  232. Base = VirtualAlloc( NULL, 0xFFFF, MEM_RESERVE, PAGE_READWRITE );
  233. if (Base == NULL ||
  234. !VirtualAlloc( Base, KeyValueInformation.DataLength, MEM_COMMIT, PAGE_READWRITE )
  235. ) {
  236. if (Base != NULL) {
  237. VirtualFree( Base, 0, MEM_RELEASE );
  238. }
  239. NtClose( Key );
  240. return NULL;
  241. }
  242. Status = NtQueryValueKey( Key,
  243. &ValueName,
  244. KeyValueFullInformation,
  245. &KeyValueInformation,
  246. KeyValueInformation.DataLength,
  247. &ResultLength
  248. );
  249. NtClose( Key );
  250. if (!NT_SUCCESS( Status )) {
  251. VirtualFree( Base, 0, MEM_RELEASE );
  252. return NULL;
  253. }
  254. else {
  255. Group = (PGROUP_DEF)((PCHAR)Base + KeyValueInformation.DataOffset);
  256. //
  257. // Set total size of group
  258. //
  259. Group->wReserved = (WORD)(ResultLength - KeyValueInformation.DataOffset);
  260. RtlMoveMemory( Base, Group, Group->wReserved );
  261. return (PGROUP_DEF)Base;
  262. }
  263. }
  264. BOOL
  265. SaveGroup(
  266. HANDLE GroupsKey,
  267. PWSTR GroupName,
  268. PGROUP_DEF Group
  269. )
  270. {
  271. NTSTATUS Status;
  272. UNICODE_STRING KeyName, ValueName;
  273. HANDLE Key;
  274. OBJECT_ATTRIBUTES ObjectAttributes;
  275. ULONG CreateDisposition;
  276. LONG ValueLength;
  277. RtlInitUnicodeString( &KeyName, GroupName );
  278. InitializeObjectAttributes( &ObjectAttributes,
  279. &KeyName,
  280. OBJ_CASE_INSENSITIVE,
  281. GroupsKey,
  282. NULL
  283. );
  284. Status = NtCreateKey( &Key,
  285. STANDARD_RIGHTS_WRITE |
  286. KEY_QUERY_VALUE |
  287. KEY_ENUMERATE_SUB_KEYS |
  288. KEY_SET_VALUE |
  289. KEY_CREATE_SUB_KEY,
  290. &ObjectAttributes,
  291. 0,
  292. NULL,
  293. 0,
  294. &CreateDisposition
  295. );
  296. if (!NT_SUCCESS( Status )) {
  297. BaseSetLastNTError( Status );
  298. return FALSE;
  299. }
  300. ValueLength = (LONG)((ULONG)Group->wReserved);
  301. Group->wReserved = 0;
  302. Group->wCheckSum = (WORD)-ValueLength;
  303. RtlInitUnicodeString( &ValueName, L"" );
  304. Status = NtSetValueKey( Key,
  305. &ValueName,
  306. 0,
  307. REG_BINARY,
  308. Group,
  309. ValueLength
  310. );
  311. Group->wReserved = (WORD)ValueLength;
  312. Group->wCheckSum = 0;
  313. NtClose( Key );
  314. if (!NT_SUCCESS( Status )) {
  315. return FALSE;
  316. }
  317. else {
  318. return TRUE;
  319. }
  320. }
  321. BOOL
  322. DeleteGroup(
  323. HANDLE GroupsKey,
  324. PWSTR GroupName
  325. )
  326. {
  327. NTSTATUS Status;
  328. UNICODE_STRING KeyName;
  329. HANDLE Key;
  330. OBJECT_ATTRIBUTES ObjectAttributes;
  331. RtlInitUnicodeString( &KeyName, GroupName );
  332. InitializeObjectAttributes( &ObjectAttributes,
  333. &KeyName,
  334. OBJ_CASE_INSENSITIVE,
  335. GroupsKey,
  336. NULL
  337. );
  338. Status = NtOpenKey( &Key,
  339. STANDARD_RIGHTS_WRITE |
  340. DELETE |
  341. KEY_QUERY_VALUE |
  342. KEY_ENUMERATE_SUB_KEYS |
  343. KEY_SET_VALUE |
  344. KEY_CREATE_SUB_KEY,
  345. &ObjectAttributes
  346. );
  347. if (!NT_SUCCESS( Status )) {
  348. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  349. return TRUE;
  350. }
  351. else {
  352. BaseSetLastNTError( Status );
  353. return FALSE;
  354. }
  355. }
  356. Status = NtDeleteKey( Key );
  357. NtClose( Key );
  358. if (!NT_SUCCESS( Status )) {
  359. return FALSE;
  360. }
  361. else {
  362. return TRUE;
  363. }
  364. }
  365. BOOL
  366. UnloadGroup(
  367. PGROUP_DEF Group
  368. )
  369. {
  370. return VirtualFree( Group, 0, MEM_RELEASE );
  371. }
  372. BOOL
  373. ExtendGroup(
  374. PGROUP_DEF Group,
  375. BOOL AppendToGroup,
  376. DWORD cb
  377. )
  378. {
  379. PBYTE Start, Commit, End;
  380. if (((DWORD)Group->wReserved + cb) > 0xFFFF) {
  381. return FALSE;
  382. }
  383. Start = (PBYTE)Group + Group->cbGroup;
  384. End = Start + cb;
  385. if (PAGE_NUMBER( Group->wReserved ) != PAGE_NUMBER( Group->wReserved + cb )) {
  386. Commit = (PBYTE)ROUND_UP( (PBYTE)Group + Group->wReserved, PAGE_SIZE );
  387. if (!VirtualAlloc( Commit, ROUND_UP( cb, PAGE_SIZE ), MEM_COMMIT, PAGE_READWRITE )) {
  388. return FALSE;
  389. }
  390. }
  391. if (!AppendToGroup) {
  392. memmove( End, Start, Group->wReserved - Group->cbGroup );
  393. }
  394. Group->wReserved += (WORD)cb;
  395. return TRUE;
  396. }
  397. WORD
  398. AddDataToGroup(
  399. PGROUP_DEF Group,
  400. PBYTE Data,
  401. DWORD cb
  402. )
  403. {
  404. WORD Offset;
  405. if (cb == 0) {
  406. cb = strlen( Data ) + 1;
  407. }
  408. cb = (DWORD)ROUND_UP( cb, sizeof( DWORD ) );
  409. if (!ExtendGroup( Group, FALSE, cb )) {
  410. return 0;
  411. }
  412. if (((DWORD)Group->cbGroup + cb) > 0xFFFF) {
  413. return 0;
  414. }
  415. Offset = Group->cbGroup;
  416. Group->cbGroup += (WORD)cb;
  417. if (Data != NULL) {
  418. memmove( (PBYTE)Group + Offset, Data, cb );
  419. }
  420. else {
  421. memset( (PBYTE)Group + Offset, 0, cb );
  422. }
  423. return Offset;
  424. }
  425. BOOL
  426. AddTagToGroup(
  427. PGROUP_DEF Group,
  428. WORD wID,
  429. WORD wItem,
  430. WORD cb,
  431. PBYTE rgb
  432. )
  433. {
  434. WORD Offset;
  435. PTAG_DEF Tag;
  436. cb = (WORD)(ROUND_UP( cb, sizeof( DWORD ) ));
  437. Offset = Group->wReserved;
  438. if (!ExtendGroup( Group, TRUE, FIELD_OFFSET( TAG_DEF, rgb[ 0 ] ) + cb )) {
  439. return FALSE;
  440. }
  441. Tag = (PTAG_DEF)PTR( Group, Offset );
  442. Tag->wID = wID;
  443. Tag->dummy1 = 0;
  444. Tag->wItem = (int)wItem;
  445. Tag->dummy2 = 0;
  446. if (cb != 0 || rgb != NULL) {
  447. Tag->cb = (WORD)(cb + FIELD_OFFSET( TAG_DEF, rgb[ 0 ] ));
  448. memmove( &Tag->rgb[ 0 ], rgb, cb );
  449. }
  450. else {
  451. Tag->cb = 0;
  452. }
  453. return TRUE;
  454. }
  455. ULONG MonoChromePalette[] = {
  456. 0x00000000, 0x00ffffff
  457. };
  458. BITMAPINFOHEADER DefaultQuestionIconBIH = {
  459. 0x00000028,
  460. 0x00000020,
  461. 0x00000040,
  462. 0x0001,
  463. 0x0004,
  464. 0x00000000,
  465. 0x00000280,
  466. 0x00000000,
  467. 0x00000000,
  468. 0xFFFFFFFF,
  469. 0x00000000
  470. };
  471. ULONG DefaultQuestionIconBits[] = {
  472. 0x00000000, 0x00000000, 0x00000000, 0x00000000
  473. , 0x00000000, 0x33000000, 0x00000030, 0x00000000
  474. , 0x00000000, 0xbb080000, 0x00000083, 0x00000000
  475. , 0x00000000, 0xff0b0000, 0x000000b3, 0x00000000
  476. , 0x00000000, 0xff0b0000, 0x000000b3, 0x00000000
  477. , 0x00000000, 0xbb000000, 0x00000080, 0x00000000
  478. , 0x00000000, 0x00000000, 0x00000000, 0x00000000
  479. , 0x00000000, 0x00000000, 0x00000000, 0x00000000
  480. , 0x00000000, 0x00000000, 0x00000000, 0x00000000
  481. , 0x00000000, 0x33000000, 0x00000030, 0x00000000
  482. , 0x00000000, 0xbb080000, 0x00000083, 0x00000000
  483. , 0x00000000, 0xbb0b0000, 0x000000b3, 0x00000000
  484. , 0x00000000, 0xff0b0000, 0x000000b3, 0x00000000
  485. , 0x00000000, 0xff0b0000, 0x000030b8, 0x00000000
  486. , 0x00000000, 0xbf000000, 0x000083bb, 0x00000000
  487. , 0x00000000, 0xbf000000, 0x0033b8fb, 0x00000000
  488. , 0x00000000, 0x0b000000, 0x33b8bbbf, 0x00000000
  489. , 0x00000000, 0x00000000, 0xb3bbfbbb, 0x00000030
  490. , 0x00000000, 0x00000000, 0xbbbbbb00, 0x00000030
  491. , 0x00000000, 0x00000000, 0xbbbb0000, 0x00000083
  492. , 0x00000000, 0x00000000, 0xbb0b0000, 0x000000b3
  493. , 0x00000000, 0x00003033, 0xbb0b0000, 0x000000b3
  494. , 0x08000000, 0x000083bb, 0xbb0b0000, 0x000000b3
  495. , 0x0b000000, 0x0000b3bb, 0xbb0b0000, 0x000000b3
  496. , 0x0b000000, 0x0030b8ff, 0xbb3b0000, 0x000000b3
  497. , 0x0b000000, 0x0083bbff, 0xbb8b0300, 0x000000b3
  498. , 0x00000000, 0x33b8fbbf, 0xbbbb3833, 0x00000080
  499. , 0x00000000, 0xbbbbffbb, 0xb8bbbbbb, 0x00000030
  500. , 0x00000000, 0xbbffbf0b, 0x83bbbbbb, 0x00000000
  501. , 0x00000000, 0xffbf0b00, 0x00b8bbff, 0x00000000
  502. , 0x00000000, 0xbb0b0000, 0x0000b8bb, 0x00000000
  503. , 0x00000000, 0x00000000, 0x00000000, 0x00000000
  504. , 0xff7ffcff, 0xff3ff8ff, 0xff1ff0ff, 0xff1ff0ff
  505. , 0xff1ff0ff, 0xff3ff8ff, 0xff7ffcff, 0xffffffff
  506. , 0xff7ffcff, 0xff3ff8ff, 0xff1ff0ff, 0xff1ff0ff
  507. , 0xff1ff0ff, 0xff0ff0ff, 0xff03f8ff, 0xff00f8ff
  508. , 0x7f00fcff, 0x3f00feff, 0x3f00ffff, 0x1fc0ffff
  509. , 0x1ff01fff, 0x1ff00ffe, 0x1ff007fc, 0x1ff007fc
  510. , 0x1fe003fc, 0x1f0000fc, 0x3f0000fe, 0x3f0000fe
  511. , 0x7f0000ff, 0xff0080ff, 0xff03e0ff, 0xff0ff8ff
  512. };
  513. BOOL
  514. ConvertIconBits(
  515. PCURSORSHAPE_16 pIconHeader
  516. );
  517. BOOL
  518. ConvertIconBits(
  519. PCURSORSHAPE_16 pIconHeader
  520. )
  521. {
  522. PBYTE Src;
  523. UINT cbScanLine;
  524. UINT nScanLine;
  525. UINT i, j, k;
  526. PBYTE Plane0;
  527. PBYTE Plane1;
  528. PBYTE Plane2;
  529. PBYTE Plane3;
  530. PBYTE p;
  531. BYTE Color0, Color1, Color2, Color3, FourColor, FourColorPlane[ 32 * 4 * 4 ];
  532. Src = (PBYTE)(pIconHeader + 1) + (pIconHeader->cbWidth * pIconHeader->cy);
  533. cbScanLine = (((pIconHeader->cx * pIconHeader->BitsPixel + 31) & ~31) / 8);
  534. nScanLine = pIconHeader->cy;
  535. if (pIconHeader->Planes != 4) {
  536. return FALSE;
  537. }
  538. else
  539. if (pIconHeader->BitsPixel != 1) {
  540. return FALSE;
  541. }
  542. else
  543. if (pIconHeader->cx != pIconHeader->cy) {
  544. return FALSE;
  545. }
  546. else
  547. if (nScanLine != 32) {
  548. return FALSE;
  549. }
  550. else
  551. if (cbScanLine != 4) {
  552. return FALSE;
  553. }
  554. Plane0 = (PBYTE)Src;
  555. Plane1 = Plane0 + cbScanLine;
  556. Plane2 = Plane1 + cbScanLine;
  557. Plane3 = Plane2 + cbScanLine;
  558. p = &FourColorPlane[ 0 ];
  559. j = nScanLine;
  560. while (j--) {
  561. k = cbScanLine;
  562. while (k--) {
  563. Color0 = *Plane0++;
  564. Color1 = *Plane1++;
  565. Color2 = *Plane2++;
  566. Color3 = *Plane3++;
  567. i = 4;
  568. while (i--) {
  569. FourColor = 0;
  570. if (Color0 & 0x80) {
  571. FourColor |= 0x10;
  572. }
  573. if (Color1 & 0x80) {
  574. FourColor |= 0x20;
  575. }
  576. if (Color2 & 0x80) {
  577. FourColor |= 0x40;
  578. }
  579. if (Color3 & 0x80) {
  580. FourColor |= 0x80;
  581. }
  582. if (Color0 & 0x40) {
  583. FourColor |= 0x01;
  584. }
  585. if (Color1 & 0x40) {
  586. FourColor |= 0x02;
  587. }
  588. if (Color2 & 0x40) {
  589. FourColor |= 0x04;
  590. }
  591. if (Color3 & 0x40) {
  592. FourColor |= 0x08;
  593. }
  594. Color0 <<= 2;
  595. Color1 <<= 2;
  596. Color2 <<= 2;
  597. Color3 <<= 2;
  598. *p++ = FourColor;
  599. }
  600. }
  601. Plane0 += 3 * cbScanLine;
  602. Plane1 += 3 * cbScanLine;
  603. Plane2 += 3 * cbScanLine;
  604. Plane3 += 3 * cbScanLine;
  605. }
  606. memmove( Src, &FourColorPlane[ 0 ], sizeof( FourColorPlane ) );
  607. pIconHeader->BitsPixel = 4;
  608. pIconHeader->Planes = 1;
  609. pIconHeader->cbWidth = cbScanLine * 4;
  610. return TRUE;
  611. }
  612. VOID
  613. CopyIconBits(
  614. PBYTE Dst,
  615. PBYTE Src,
  616. UINT cbScanLine,
  617. UINT nScanLine
  618. );
  619. VOID
  620. CopyIconBits(
  621. PBYTE Dst,
  622. PBYTE Src,
  623. UINT cbScanLine,
  624. UINT nScanLine
  625. )
  626. {
  627. Src += (cbScanLine * nScanLine);
  628. while (nScanLine--) {
  629. Src -= cbScanLine;
  630. memcpy( Dst, Src, cbScanLine );
  631. Dst += cbScanLine;
  632. }
  633. }
  634. typedef struct _WIN31_GROUP_ITEM_DESC {
  635. LPSTR GroupName;
  636. LPSTR ItemName;
  637. } WIN31_GROUP_ITEM_DESC, *PWIN31_GROUP_ITEM_DESC;
  638. WIN31_GROUP_ITEM_DESC GroupItemsToIgnore[] = {
  639. {"Main", "File Manager"},
  640. {NULL, "Control Panel"},
  641. {NULL, "Print Manager"},
  642. {NULL, "ClipBook Viewer"},
  643. {NULL, "MS-DOS Prompt"},
  644. {NULL, "Windows Setup"},
  645. {NULL, "Read Me"},
  646. {"Accessories", "Paintbrush"},
  647. {NULL, "Write"},
  648. {NULL, "Terminal"},
  649. {NULL, "Notepad"},
  650. {NULL, "Recorder"},
  651. {NULL, "Clock"},
  652. {NULL, "Object Packager"},
  653. {NULL, "Media Player"},
  654. {NULL, "Sound Recorder"},
  655. {"Network", NULL},
  656. {NULL, NULL}
  657. };
  658. PGROUP_DEF
  659. CreateGroupFromGroup16(
  660. LPSTR GroupName,
  661. PGROUP_DEF16 Group16
  662. )
  663. {
  664. PWIN31_GROUP_ITEM_DESC p1, ItemsToIgnore;
  665. PGROUP_DEF Group;
  666. PITEM_DEF Item;
  667. PITEM_DEF16 Item16;
  668. PTAG_DEF16 Tag16;
  669. DWORD cb;
  670. PBYTE p;
  671. LPSTR s;
  672. UINT i;
  673. PCURSORSHAPE_16 pIconHeader;
  674. PBITMAPINFOHEADER pbmi;
  675. BOOL bUserDefaultIcon, bItemConvertedOkay;
  676. int imagesize, colorsize, masksize, bmisize;
  677. ItemsToIgnore = NULL;
  678. p1 = GroupItemsToIgnore;
  679. while (p1->GroupName || p1->ItemName) {
  680. if (p1->GroupName &&
  681. !_stricmp( p1->GroupName, GroupName )
  682. ) {
  683. if (p1->ItemName == NULL) {
  684. return (PGROUP_DEF)-1;
  685. }
  686. ItemsToIgnore = p1;
  687. break;
  688. }
  689. p1 += 1;
  690. }
  691. Group = VirtualAlloc( NULL, 0xFFFF, MEM_RESERVE, PAGE_READWRITE );
  692. if (Group == NULL) {
  693. return NULL;
  694. }
  695. if (!VirtualAlloc( Group,
  696. cb = FIELD_OFFSET( GROUP_DEF, rgiItems[ 0 ] ),
  697. MEM_COMMIT,
  698. PAGE_READWRITE
  699. )
  700. ) {
  701. VirtualFree( Group, 0, MEM_RELEASE );
  702. return NULL;
  703. }
  704. cb = (DWORD)ROUND_UP( cb, sizeof( DWORD ) );
  705. Group->wReserved = (WORD)cb;
  706. Group->cbGroup = (WORD)cb;
  707. Group->cItems = (Group16->cItems + NSLOTS - 1) & ~(NSLOTS-1);
  708. AddDataToGroup( Group, NULL, (Group->cItems * sizeof( Group->rgiItems[ 0 ] )) );
  709. Group->pName = AddDataToGroup( Group,
  710. GroupName,
  711. 0
  712. );
  713. Group->dwMagic = GROUP_MAGIC;
  714. Group->wCheckSum = 0; /* adjusted later... */
  715. Group->nCmdShow = SW_SHOWMINIMIZED; // Group16->nCmdShow;
  716. Group->wIconFormat = Group16->wIconFormat;
  717. if (lpGetSystemMetrics == NULL) {
  718. lpGetSystemMetrics = (PGETSYSTEMMETRICS)GetProcAddress( LoadLibrary( "user32.dll" ),
  719. "GetSystemMetrics"
  720. );
  721. if (lpGetSystemMetrics == NULL) {
  722. lpGetSystemMetrics = (PGETSYSTEMMETRICS)-1;
  723. }
  724. }
  725. if (lpGetSystemMetrics != (PGETSYSTEMMETRICS)-1) {
  726. Group->cxIcon = (WORD)(*lpGetSystemMetrics)(SM_CXICON);
  727. Group->cyIcon = (WORD)(*lpGetSystemMetrics)(SM_CYICON);
  728. }
  729. Group->ptMin.x = (LONG)Group16->ptMin.x;
  730. Group->ptMin.y = (LONG)Group16->ptMin.y;
  731. Group->rcNormal.left = (int)Group16->rcNormal.Left;
  732. Group->rcNormal.top = (int)Group16->rcNormal.Top;
  733. Group->rcNormal.right = (int)Group16->rcNormal.Right;
  734. Group->rcNormal.bottom = (int)Group16->rcNormal.Bottom;
  735. for (i=0; i<Group16->cItems; i++) {
  736. if (Group16->rgiItems[ i ] == 0) {
  737. continue;
  738. }
  739. Item16 = ITEM16( Group16, i );
  740. if (p1 = ItemsToIgnore) {
  741. s = PTR( Group16, Item16->pName );
  742. do {
  743. if (!_stricmp( p1->ItemName, s )) {
  744. s = NULL;
  745. break;
  746. }
  747. p1 += 1;
  748. }
  749. while (p1->GroupName == NULL && p1->ItemName != NULL);
  750. if (s == NULL) {
  751. continue;
  752. }
  753. }
  754. Group->rgiItems[ i ] = AddDataToGroup( Group, NULL, sizeof( ITEM_DEF ) );
  755. if (Group->rgiItems[ i ] == 0) {
  756. break;
  757. }
  758. Item = ITEM( Group, i );
  759. Item->pt.x = (LONG)Item16->pt.x;
  760. Item->pt.y = (LONG)Item16->pt.y;
  761. Item->idIcon = Item16->iIcon;
  762. Item->indexIcon = Item16->iIcon;
  763. Item->wIconVer = 3;
  764. bUserDefaultIcon = FALSE;
  765. pIconHeader = (PCURSORSHAPE_16)PTR( Group16, Item16->pHeader );
  766. if (pIconHeader->Planes != 1) {
  767. if (!ConvertIconBits( pIconHeader )) {
  768. KdPrint(("WIN31IO: Invalid 16-bit item icon at %08x\n", pIconHeader ));
  769. bUserDefaultIcon = TRUE;
  770. }
  771. }
  772. else
  773. if (pIconHeader->BitsPixel != 1 &&
  774. pIconHeader->BitsPixel != 4 &&
  775. pIconHeader->BitsPixel != 8
  776. ) {
  777. bUserDefaultIcon = TRUE;
  778. }
  779. if (!bUserDefaultIcon) {
  780. bmisize = sizeof( BITMAPINFOHEADER );
  781. imagesize = Item16->cbXORPlane;
  782. masksize = Item16->cbANDPlane;
  783. if (pIconHeader->BitsPixel == 1) {
  784. colorsize = sizeof( MonoChromePalette );
  785. }
  786. else {
  787. colorsize = 0;
  788. }
  789. Item->cbIconRes = (WORD)(bmisize +
  790. colorsize +
  791. imagesize +
  792. masksize
  793. );
  794. Item->cbIconRes = (WORD)ROUND_UP( Item->cbIconRes, sizeof( DWORD ) );
  795. Item->pIconRes = AddDataToGroup( Group, NULL, Item->cbIconRes );
  796. if (Item->pIconRes != 0) {
  797. p = PTR( Group, Item->pIconRes );
  798. pbmi = (PBITMAPINFOHEADER)p;
  799. pbmi->biSize = bmisize;
  800. pbmi->biWidth = pIconHeader->cx;
  801. pbmi->biHeight = pIconHeader->cy * 2;
  802. pbmi->biPlanes = pIconHeader->Planes;
  803. pbmi->biBitCount = pIconHeader->BitsPixel;
  804. pbmi->biCompression = BI_RGB;
  805. pbmi->biSizeImage = imagesize;
  806. pbmi->biXPelsPerMeter = 0;
  807. pbmi->biYPelsPerMeter = 0;
  808. pbmi->biClrImportant = 0;
  809. if (colorsize != 0) {
  810. memcpy( p + bmisize, MonoChromePalette, colorsize );
  811. pbmi->biClrUsed = 0;
  812. }
  813. else {
  814. pbmi->biClrUsed = (DWORD)-1;
  815. }
  816. CopyIconBits( p + bmisize + colorsize,
  817. (PBYTE)PTR( Group16, Item16->pXORPlane ),
  818. (((pIconHeader->cx * pIconHeader->BitsPixel + 31) & ~31) / 8),
  819. pIconHeader->cy
  820. );
  821. CopyIconBits( p + bmisize + colorsize + imagesize,
  822. (PBYTE)PTR( Group16, Item16->pANDPlane ),
  823. (((pIconHeader->cx + 31) & ~31) / 8),
  824. pIconHeader->cy
  825. );
  826. }
  827. }
  828. else {
  829. bmisize = sizeof( DefaultQuestionIconBIH );
  830. imagesize = sizeof( DefaultQuestionIconBits );
  831. Item->cbIconRes = bmisize + imagesize;
  832. Item->cbIconRes = (WORD)ROUND_UP( Item->cbIconRes, sizeof( DWORD ) );
  833. Item->pIconRes = AddDataToGroup( Group, NULL, Item->cbIconRes );
  834. if (Item->pIconRes != 0) {
  835. p = PTR( Group, Item->pIconRes );
  836. memcpy( p, &DefaultQuestionIconBIH, bmisize );
  837. memcpy( p + bmisize, &DefaultQuestionIconBits, imagesize );
  838. }
  839. }
  840. bItemConvertedOkay = FALSE;
  841. if (Item->pIconRes != 0) {
  842. Item->pName = AddDataToGroup( Group,
  843. PTR( Group16, Item16->pName ),
  844. 0
  845. );
  846. if (Item->pName != 0) {
  847. Item->pCommand = AddDataToGroup( Group,
  848. PTR( Group16, Item16->pCommand ),
  849. 0
  850. );
  851. if (Item->pCommand != 0) {
  852. Item->pIconPath = AddDataToGroup( Group,
  853. PTR( Group16, Item16->pIconPath ),
  854. 0
  855. );
  856. if (Item->pIconPath != 0) {
  857. bItemConvertedOkay = TRUE;
  858. }
  859. }
  860. }
  861. }
  862. if (!bItemConvertedOkay) {
  863. break;
  864. }
  865. }
  866. Tag16 = (PTAG_DEF16)((PBYTE)Group16 + Group16->cbGroup);
  867. if (bItemConvertedOkay &&
  868. Tag16->wID == ID_MAGIC && Tag16->wItem == ID_LASTTAG &&
  869. *(UNALIGNED DWORD *)&Tag16->rgb[ 0 ] == PMTAG_MAGIC
  870. ) {
  871. while (Tag16->wID != ID_LASTTAG) {
  872. if (!AddTagToGroup( Group,
  873. Tag16->wID,
  874. Tag16->wItem,
  875. (WORD)(Tag16->cb - FIELD_OFFSET( TAG_DEF16, rgb[ 0 ] )),
  876. &Tag16->rgb[ 0 ]
  877. )
  878. ) {
  879. bItemConvertedOkay = FALSE;
  880. break;
  881. }
  882. Tag16 = (PTAG_DEF16)((PBYTE)Tag16 + Tag16->cb);
  883. }
  884. if (bItemConvertedOkay) {
  885. if (!AddTagToGroup( Group,
  886. ID_LASTTAG,
  887. 0xFFFF,
  888. 0,
  889. NULL
  890. )
  891. ) {
  892. bItemConvertedOkay = FALSE;
  893. }
  894. }
  895. }
  896. if (!bItemConvertedOkay) {
  897. UnloadGroup( Group );
  898. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  899. return NULL;
  900. }
  901. else {
  902. return Group;
  903. }
  904. }
  905. #if DBG
  906. BOOL
  907. DumpGroup(
  908. PWSTR GroupName,
  909. PGROUP_DEF Group
  910. )
  911. {
  912. PBITMAPINFOHEADER Icon;
  913. PICON_HEADER16 Icon16;
  914. PITEM_DEF Item;
  915. PTAG_DEF Tag;
  916. PULONG p;
  917. int cb;
  918. UINT i;
  919. DbgPrint( "%ws - Group at %08x\n", GroupName, Group );
  920. DbgPrint( " dwMagic: %08x\n", Group->dwMagic );
  921. DbgPrint( " wCheckSum: %04x\n", Group->wCheckSum );
  922. DbgPrint( " cbGroup: %04x\n", Group->cbGroup );
  923. DbgPrint( " nCmdShow: %04x\n", Group->nCmdShow );
  924. DbgPrint( " rcNormal: [%08x,%08x,%08x,%08x]\n",
  925. Group->rcNormal.left,
  926. Group->rcNormal.top,
  927. Group->rcNormal.right,
  928. Group->rcNormal.bottom
  929. );
  930. DbgPrint( " ptMin: [%08x,%08x]\n", Group->ptMin.x, Group->ptMin.y );
  931. DbgPrint( " pName: [%04x] %s\n", Group->pName, Group->pName ? (PSZ)PTR( Group, Group->pName ) : "(null)" );
  932. DbgPrint( " cxIcon: %04x\n", Group->cxIcon );
  933. DbgPrint( " cyIcon: %04x\n", Group->cyIcon );
  934. DbgPrint( " wIconFormat: %04x\n", Group->wIconFormat );
  935. DbgPrint( " wReserved: %04x\n", Group->wReserved );
  936. DbgPrint( " cItems: %04x\n", Group->cItems );
  937. for (i=0; i<Group->cItems; i++) {
  938. DbgPrint( " Item[ %02x ] at %04x\n", i, Group->rgiItems[ i ] );
  939. if (Group->rgiItems[ i ] != 0) {
  940. Item = ITEM( Group, i );
  941. DbgPrint( " pt: [%08x, %08x]\n",
  942. Item->pt.x,
  943. Item->pt.y
  944. );
  945. DbgPrint( " idIcon: %04x\n", Item->idIcon );
  946. DbgPrint( " wIconVer: %04x\n", Item->wIconVer );
  947. DbgPrint( " cbIconRes:%04x\n", Item->cbIconRes );
  948. DbgPrint( " indexIcon:%04x\n", Item->indexIcon );
  949. DbgPrint( " dummy2: %04x\n", Item->dummy2 );
  950. DbgPrint( " pIconRes: %04x\n", Item->pIconRes );
  951. if (Item->wIconVer == 2) {
  952. Icon16 = (PICON_HEADER16)PTR( Group, Item->pIconRes );
  953. DbgPrint( " xHot: %04x\n", Icon16->xHotSpot );
  954. DbgPrint( " yHot: %04x\n", Icon16->yHotSpot );
  955. DbgPrint( " cx: %04x\n", Icon16->cx );
  956. DbgPrint( " cy: %04x\n", Icon16->cy );
  957. DbgPrint( " cbWid:%04x\n", Icon16->cbWidth );
  958. DbgPrint( " Plane:%04x\n", Icon16->Planes );
  959. DbgPrint( " BPP: %04x\n", Icon16->BitsPixel );
  960. p = (PULONG)(Icon16+1);
  961. cb = Item->cbIconRes - sizeof( *Icon16 );
  962. }
  963. else {
  964. Icon = (PBITMAPINFOHEADER)PTR( Group, Item->pIconRes );
  965. DbgPrint( " biSize : %08x\n", Icon->biSize );
  966. DbgPrint( " biWidth : %08x\n", Icon->biWidth );
  967. DbgPrint( " biHeight : %08x\n", Icon->biHeight );
  968. DbgPrint( " biPlanes : %04x\n", Icon->biPlanes );
  969. DbgPrint( " biBitCount : %04x\n", Icon->biBitCount );
  970. DbgPrint( " biCompression : %08x\n", Icon->biCompression );
  971. DbgPrint( " biSizeImage : %08x\n", Icon->biSizeImage );
  972. DbgPrint( " biXPelsPerMeter: %08x\n", Icon->biXPelsPerMeter );
  973. DbgPrint( " biYPelsPerMeter: %08x\n", Icon->biYPelsPerMeter );
  974. DbgPrint( " biClrUsed : %08x\n", Icon->biClrUsed );
  975. DbgPrint( " biClrImportant : %08x\n", Icon->biClrImportant );
  976. p = (PULONG)(Icon+1);
  977. cb = Item->cbIconRes - sizeof( *Icon );
  978. }
  979. DbgPrint( " dummy3: %04x\n", Item->dummy3 );
  980. DbgPrint( " pName: [%04x] %s\n", Item->pName, PTR( Group, Item->pName ) );
  981. DbgPrint( " pCommand:[%04x] %s\n", Item->pCommand, PTR( Group, Item->pCommand ) );
  982. DbgPrint( " pIconPth:[%04x] %s\n", Item->pIconPath, PTR( Group, Item->pIconPath ) );
  983. DbgPrint( " IconData: %04x bytes\n", cb );
  984. while (cb > 0) {
  985. DbgPrint( " %08x", *p++ );
  986. cb -= sizeof( *p );
  987. if (cb >= sizeof( *p )) {
  988. cb -= sizeof( *p );
  989. DbgPrint( " %08x", *p++ );
  990. if (cb >= sizeof( *p )) {
  991. cb -= sizeof( *p );
  992. DbgPrint( " %08x", *p++ );
  993. if (cb >= sizeof( *p )) {
  994. cb -= sizeof( *p );
  995. DbgPrint( " %08x", *p++ );
  996. }
  997. }
  998. }
  999. DbgPrint( "\n" );
  1000. }
  1001. }
  1002. }
  1003. Tag = (PTAG_DEF)((PBYTE)Group + Group->cbGroup);
  1004. if (Tag->wID == ID_MAGIC && Tag->wItem == ID_LASTTAG &&
  1005. *(LPDWORD)&Tag->rgb == PMTAG_MAGIC
  1006. ) {
  1007. while (Tag->wID != ID_LASTTAG) {
  1008. DbgPrint( " Tag at %04x\n", (PBYTE)Tag - (PBYTE)Group );
  1009. DbgPrint( " wID: %04x\n", Tag->wID );
  1010. DbgPrint( " dummy1: %04x\n", Tag->dummy1 );
  1011. DbgPrint( " wItem: %08x\n", Tag->wItem );
  1012. DbgPrint( " cb: %04x\n", Tag->cb );
  1013. DbgPrint( " dummy2: %04x\n", Tag->dummy2 );
  1014. switch( Tag->wID ) {
  1015. case ID_MAGIC:
  1016. DbgPrint( " rgb: ID_MAGIC( %.4s )\n", Tag->rgb );
  1017. break;
  1018. case ID_WRITERVERSION:
  1019. DbgPrint( " rgb: ID_WRITERVERSION( %s )\n", Tag->rgb );
  1020. break;
  1021. case ID_APPLICATIONDIR:
  1022. DbgPrint( " rgb: ID_APPLICATIONDIR( %s )\n", Tag->rgb );
  1023. break;
  1024. case ID_HOTKEY:
  1025. DbgPrint( " rgb: ID_HOTKEY( %04x )\n", *(LPWORD)Tag->rgb );
  1026. break;
  1027. case ID_MINIMIZE:
  1028. DbgPrint( " rgb: ID_MINIMIZE()\n" );
  1029. break;
  1030. case ID_LASTTAG:
  1031. DbgPrint( " rgb: ID_LASTTAG()\n" );
  1032. break;
  1033. default:
  1034. DbgPrint( " rgb: unknown data format for this ID\n" );
  1035. break;
  1036. }
  1037. Tag = (PTAG_DEF)((PBYTE)Tag + Tag->cb);
  1038. }
  1039. }
  1040. return TRUE;
  1041. }
  1042. #endif // DBG