Reactos
at master 752 lines 22 kB view raw
1/* 2 * Program Manager 3 * 4 * Copyright 1996 Ulrich Schmid 5 * 1997 Peter Schlaile 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22#include "progman.h" 23 24#if 0 25#define MALLOCHUNK 1000 26 27#define GET_USHORT(buffer, i)\ 28 (((BYTE)((buffer)[(i)]) + 0x100 * (BYTE)((buffer)[(i)+1]))) 29#define GET_SHORT(buffer, i)\ 30 (((BYTE)((buffer)[(i)]) + 0x100 * (signed char)((buffer)[(i)+1]))) 31#define PUT_SHORT(buffer, i, s)\ 32 (((buffer)[(i)] = (s) & 0xff, (buffer)[(i)+1] = ((s) >> 8) & 0xff)) 33 34static BOOL GRPFILE_ReadFileToBuffer(LPCSTR, HLOCAL*, INT*); 35static HLOCAL GRPFILE_ScanGroup(LPCSTR, INT, LPCSTR, BOOL); 36static HLOCAL GRPFILE_ScanProgram(LPCSTR, INT, LPCSTR, INT, 37 LPCSTR, HLOCAL,LPCSTR); 38static BOOL GRPFILE_DoWriteGroupFile(HFILE file, PROGGROUP *group); 39#endif 40 41/*********************************************************************** 42 * 43 * GRPFILE_ModifyFileName 44 * 45 * Change extension `.grp' to `.gr' 46 */ 47 48#if 0 49static VOID GRPFILE_ModifyFileName(LPSTR lpszNewName, LPCSTR lpszOrigName, 50 INT nSize, BOOL bModify) 51{ 52 lstrcpynA(lpszNewName, lpszOrigName, nSize); 53 lpszNewName[nSize-1] = '\0'; 54 if (!bModify) return; 55 if (!lstrcmpiA(lpszNewName + strlen(lpszNewName) - 4, ".grp")) 56 lpszNewName[strlen(lpszNewName) - 1] = '\0'; 57} 58#endif 59 60/*********************************************************************** 61 * 62 * GRPFILE_ReadGroupFile 63 */ 64 65DWORD GRPFILE_ReadGroupFile(LPCWSTR lpszPath, BOOL bIsCommonGroup) 66{ 67#if 0 68 CHAR szPath_gr[MAX_PATHNAME_LEN]; 69 BOOL bFileNameModified = FALSE; 70 OFSTRUCT dummy; 71 HLOCAL hBuffer, hGroup; 72 INT size; 73 74 /* if `.gr' file exists use that */ 75 GRPFILE_ModifyFileName(szPath_gr, lpszPath, MAX_PATHNAME_LEN, TRUE); 76 if (OpenFile(szPath_gr, &dummy, OF_EXIST) != HFILE_ERROR) 77 { 78 lpszPath = szPath_gr; 79 bFileNameModified = TRUE; 80 } 81 82 /* Read the whole file into a buffer */ 83 if (!GRPFILE_ReadFileToBuffer(lpszPath, &hBuffer, &size)) 84 { 85 MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s, lpszPath, IDS_ERROR, MB_YESNO); 86 return(0); 87 } 88 89 /* Interpret buffer */ 90 hGroup = GRPFILE_ScanGroup(LocalLock(hBuffer), size, 91 lpszPath, bFileNameModified); 92 if (!hGroup) 93 MAIN_MessageBoxIDS_s(IDS_GRPFILE_READ_ERROR_s, lpszPath, IDS_ERROR, MB_YESNO); 94 95 LocalFree(hBuffer); 96 97 return(hGroup); 98 99#else 100 return ERROR_SUCCESS; 101#endif 102} 103 104/*********************************************************************** 105 * 106 * GRPFILE_ReadFileToBuffer 107 */ 108 109#if 0 110static BOOL GRPFILE_ReadFileToBuffer(LPCSTR path, HLOCAL *phBuffer, 111 INT *piSize) 112{ 113 UINT len, size; 114 LPSTR buffer; 115 HLOCAL hBuffer, hNewBuffer; 116 HFILE file; 117 118 file=_lopen(path, OF_READ); 119 if (file == HFILE_ERROR) return FALSE; 120 121 size = 0; 122 hBuffer = LocalAlloc(LMEM_FIXED, MALLOCHUNK + 1); 123 if (!hBuffer) return FALSE; 124 buffer = LocalLock(hBuffer); 125 126 while ((len = _lread(file, buffer + size, MALLOCHUNK)) 127 == MALLOCHUNK) 128 { 129 size += len; 130 hNewBuffer = LocalReAlloc(hBuffer, size + MALLOCHUNK + 1, 131 LMEM_MOVEABLE); 132 if (!hNewBuffer) 133 { 134 LocalFree(hBuffer); 135 return FALSE; 136 } 137 hBuffer = hNewBuffer; 138 buffer = LocalLock(hBuffer); 139 } 140 141 _lclose(file); 142 143 if (len == (UINT)HFILE_ERROR) 144 { 145 LocalFree(hBuffer); 146 return FALSE; 147 } 148 149 size += len; 150 buffer[size] = 0; 151 152 *phBuffer = hBuffer; 153 *piSize = size; 154 return TRUE; 155} 156#endif 157 158/*********************************************************************** 159 * GRPFILE_ScanGroup 160 */ 161 162#if 0 163static HLOCAL GRPFILE_ScanGroup(LPCSTR buffer, INT size, 164 LPCSTR lpszGrpFile, 165 BOOL bModifiedFileName) 166{ 167 HLOCAL hGroup; 168 INT i, seqnum; 169 LPCSTR extension; 170 LPCSTR lpszName; 171 INT x, y, width, height, iconx, icony, nCmdShow; 172 INT number_of_programs; 173 BOOL bOverwriteFileOk; 174 175 if (buffer[0] != 'P' || buffer[1] != 'M') return(0); 176 if (buffer[2] == 'C' && buffer[3] == 'C') 177 /* original with checksum */ 178 bOverwriteFileOk = FALSE; 179 else if (buffer[2] == 'X' && buffer[3] == 'X') 180 /* modified without checksum */ 181 bOverwriteFileOk = TRUE; 182 else return(0); 183 184 /* checksum = GET_USHORT(buffer, 4) (ignored) */ 185 186 extension = buffer + GET_USHORT(buffer, 6); 187 if (extension == buffer + size) extension = 0; 188 else if (extension + 6 > buffer + size) return(0); 189 190 nCmdShow = GET_USHORT(buffer, 8); 191 x = GET_SHORT(buffer, 10); 192 y = GET_SHORT(buffer, 12); 193 width = GET_USHORT(buffer, 14); 194 height = GET_USHORT(buffer, 16); 195 iconx = GET_SHORT(buffer, 18); 196 icony = GET_SHORT(buffer, 20); 197 lpszName = buffer + GET_USHORT(buffer, 22); 198 if (lpszName >= buffer + size) return(0); 199 200 /* unknown bytes 24 - 31 ignored */ 201 /* 202 Unknown bytes should be: 203 wLogPixelsX = GET_SHORT(buffer, 24); 204 wLogPixelsY = GET_SHORT(buffer, 26); 205 byBitsPerPixel = byte at 28; 206 byPlanes = byte at 29; 207 wReserved = GET_SHORT(buffer, 30); 208 */ 209 210 hGroup = GROUP_AddGroup(lpszName, lpszGrpFile, nCmdShow, x, y, 211 width, height, iconx, icony, 212 bModifiedFileName, bOverwriteFileOk, 213 TRUE); 214 if (!hGroup) return(0); 215 216 number_of_programs = GET_USHORT(buffer, 32); 217 if (2 * number_of_programs + 34 > size) return(0); 218 for (i=0, seqnum=0; i < number_of_programs; i++, seqnum++) 219 { 220 LPCSTR program_ptr = buffer + GET_USHORT(buffer, 34 + 2*i); 221 if (program_ptr + 24 > buffer + size) return(0); 222 if (!GET_USHORT(buffer, 34 + 2*i)) continue; 223 if (!GRPFILE_ScanProgram(buffer, size, program_ptr, seqnum, 224 extension, hGroup, lpszGrpFile)) 225 { 226 GROUP_DeleteGroup(hGroup); 227 return(0); 228 } 229 } 230 231 /* FIXME shouldn't be necessary */ 232 GROUP_ShowGroupWindow(hGroup); 233 234 return hGroup; 235} 236#endif 237 238/*********************************************************************** 239 * GRPFILE_ScanProgram 240 */ 241 242#if 0 243static HLOCAL GRPFILE_ScanProgram(LPCSTR buffer, INT size, 244 LPCSTR program_ptr, INT seqnum, 245 LPCSTR extension, HLOCAL hGroup, 246 LPCSTR lpszGrpFile) 247{ 248 INT icontype; 249 HICON hIcon; 250 LPCSTR lpszName, lpszCmdLine, lpszIconFile, lpszWorkDir; 251 LPCSTR iconinfo_ptr, iconANDbits_ptr, iconXORbits_ptr; 252 INT x, y, nIconIndex, iconANDsize, iconXORsize; 253 INT nHotKey, nCmdShow; 254 UINT width, height, planes, bpp; 255 256 x = GET_SHORT(program_ptr, 0); 257 y = GET_SHORT(program_ptr, 2); 258 nIconIndex = GET_USHORT(program_ptr, 4); 259 260 /* FIXME is this correct ?? */ 261 icontype = GET_USHORT(program_ptr, 6); 262 switch (icontype) 263 { 264 default: 265 MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s, lpszGrpFile, 266 IDS_WARNING, MB_OK); 267 case 0x048c: 268 iconXORsize = GET_USHORT(program_ptr, 8); 269 iconANDsize = GET_USHORT(program_ptr, 10) / 8; 270 iconinfo_ptr = buffer + GET_USHORT(program_ptr, 12); 271 iconXORbits_ptr = buffer + GET_USHORT(program_ptr, 14); 272 iconANDbits_ptr = buffer + GET_USHORT(program_ptr, 16); 273 width = GET_USHORT(iconinfo_ptr, 4); 274 height = GET_USHORT(iconinfo_ptr, 6); 275 planes = GET_USHORT(iconinfo_ptr, 10); 276 bpp = GET_USHORT(iconinfo_ptr, 11); 277 break; 278 case 0x000c: 279 iconANDsize = GET_USHORT(program_ptr, 8); 280 iconXORsize = GET_USHORT(program_ptr, 10); 281 iconinfo_ptr = buffer + GET_USHORT(program_ptr, 12); 282 iconANDbits_ptr = buffer + GET_USHORT(program_ptr, 14); 283 iconXORbits_ptr = buffer + GET_USHORT(program_ptr, 16); 284 width = GET_USHORT(iconinfo_ptr, 4); 285 height = GET_USHORT(iconinfo_ptr, 6); 286 planes = GET_USHORT(iconinfo_ptr, 10); 287 bpp = GET_USHORT(iconinfo_ptr, 11); 288 } 289 290 if (iconANDbits_ptr + iconANDsize > buffer + size || 291 iconXORbits_ptr + iconXORsize > buffer + size) return(0); 292 293 hIcon = CreateIcon(Globals.hInstance, width, height, planes, bpp, (PBYTE)iconANDbits_ptr, (PBYTE)iconXORbits_ptr); 294 295 lpszName = buffer + GET_USHORT(program_ptr, 18); 296 lpszCmdLine = buffer + GET_USHORT(program_ptr, 20); 297 lpszIconFile = buffer + GET_USHORT(program_ptr, 22); 298 if (iconinfo_ptr + 6 > buffer + size || 299 lpszName > buffer + size || 300 lpszCmdLine > buffer + size || 301 lpszIconFile > buffer + size) return(0); 302 303 /* Scan Extensions */ 304 lpszWorkDir = ""; 305 nHotKey = 0; 306 nCmdShow = SW_SHOWNORMAL; 307 if (extension) 308 { 309 LPCSTR ptr = extension; 310 while (ptr + 6 <= buffer + size) 311 { 312 UINT type = GET_USHORT(ptr, 0); 313 UINT number = GET_USHORT(ptr, 2); 314 UINT skip = GET_USHORT(ptr, 4); 315 316 if (number == seqnum) 317 { 318 switch (type) 319 { 320 case 0x8000: 321 if (ptr + 10 > buffer + size) return(0); 322 if (ptr[6] != 'P' || ptr[7] != 'M' || 323 ptr[8] != 'C' || ptr[9] != 'C') return(0); 324 break; 325 case 0x8101: 326 lpszWorkDir = ptr + 6; 327 break; 328 case 0x8102: 329 if (ptr + 8 > buffer + size) return(0); 330 nHotKey = GET_USHORT(ptr, 6); 331 break; 332 case 0x8103: 333 if (ptr + 8 > buffer + size) return(0); 334 nCmdShow = GET_USHORT(ptr, 6); 335 break; 336 default: 337 MAIN_MessageBoxIDS_s(IDS_UNKNOWN_FEATURE_s, 338 lpszGrpFile, IDS_WARNING, MB_OK); 339 } 340 } 341 if (!skip) break; 342 ptr += skip; 343 } 344 } 345 346 return (PROGRAM_AddProgram(hGroup, hIcon, lpszName, x, y, 347 lpszCmdLine, lpszIconFile, 348 nIconIndex, lpszWorkDir, 349 nHotKey, nCmdShow)); 350} 351#endif 352 353/*********************************************************************** 354 * 355 * GRPFILE_WriteGroupFile 356 */ 357 358BOOL GRPFILE_WriteGroupFile(PROGGROUP* hGroup) 359{ 360#if 0 361 CHAR szPath[MAX_PATHNAME_LEN]; 362 PROGGROUP *group = LocalLock(hGroup); 363 OFSTRUCT dummy; 364 HFILE file; 365 BOOL ret; 366 367 GRPFILE_ModifyFileName(szPath, LocalLock(group->hGrpFile), 368 MAX_PATHNAME_LEN, 369 group->bFileNameModified); 370 371 /* Try not to overwrite original files */ 372 373 /* group->bOverwriteFileOk == TRUE only if a file has the modified format */ 374 if (!group->bOverwriteFileOk && 375 OpenFile(szPath, &dummy, OF_EXIST) != HFILE_ERROR) 376 { 377 /* Original file exists, try `.gr' extension */ 378 GRPFILE_ModifyFileName(szPath, LocalLock(group->hGrpFile), 379 MAX_PATHNAME_LEN, TRUE); 380 if (OpenFile(szPath, &dummy, OF_EXIST) != HFILE_ERROR) 381 { 382 /* File exists. Do not overwrite */ 383 MAIN_MessageBoxIDS_s(IDS_FILE_NOT_OVERWRITTEN_s, szPath, 384 IDS_INFO, MB_OK); 385 return FALSE; 386 } 387 /* Inform about the modified file name */ 388 if (IDCANCEL == 389 MAIN_MessageBoxIDS_s(IDS_SAVE_GROUP_AS_s, szPath, IDS_INFO, 390 MB_OKCANCEL | MB_ICONINFORMATION)) 391 return FALSE; 392 } 393 394 { 395 /* Warn about the (possible) incompatibility */ 396 CHAR msg[MAX_PATHNAME_LEN + 200]; 397 wsprintfA(msg, 398 "Group files written by this DRAFT Program Manager " 399 "possibly cannot be read by the Microsoft Program Manager!!\n" 400 "Are you sure to write %s?", szPath); 401 if (IDOK != MessageBoxA(Globals.hMainWnd, msg, "WARNING", 402 MB_OKCANCEL | MB_DEFBUTTON2)) return FALSE; 403 } 404 405 /* Open file */ 406 file = _lcreat(szPath, 0); 407 if (file != HFILE_ERROR) 408 { 409 ret = GRPFILE_DoWriteGroupFile(file, group); 410 _lclose(file); 411 } 412 else ret = FALSE; 413 414 if (!ret) 415 MAIN_MessageBoxIDS_s(IDS_FILE_WRITE_ERROR_s, szPath, IDS_ERROR, MB_OK); 416 417 return(ret); 418 419#else 420 return TRUE; 421#endif 422} 423 424#if 0 425 426/*********************************************************************** 427 * 428 * GRPFILE_CalculateSizes 429 */ 430 431static VOID GRPFILE_CalculateSizes(PROGRAM *program, INT *Progs, INT *Icons, 432 UINT *sizeAnd, UINT *sizeXor) 433{ 434 ICONINFO info; 435 BITMAP bmp; 436 437 GetIconInfo( program->hIcon, &info ); 438 GetObjectW( info.hbmMask, sizeof(bmp), &bmp ); 439 *sizeAnd = bmp.bmHeight * ((bmp.bmWidth + 15) / 16 * 2); 440 GetObjectW( info.hbmColor, sizeof(bmp), &bmp ); 441 *sizeXor = bmp.bmHeight * bmp.bmWidthBytes; 442 DeleteObject( info.hbmMask ); 443 DeleteObject( info.hbmColor ); 444 445 *Progs += 24; 446 *Progs += strlen(LocalLock(program->hName)) + 1; 447 *Progs += strlen(LocalLock(program->hCmdLine)) + 1; 448 *Progs += strlen(LocalLock(program->hIconFile)) + 1; 449 450 *Icons += 12; /* IconInfo */ 451 *Icons += *sizeAnd; 452 *Icons += *sizeXor; 453} 454 455/***********************************************************************/ 456UINT16 GRPFILE_checksum; 457BOOL GRPFILE_checksum_half_word; 458BYTE GRPFILE_checksum_last_byte; 459/*********************************************************************** 460 * 461 * GRPFILE_InitChecksum 462 */ 463 464static void GRPFILE_InitChecksum(void) 465{ 466 GRPFILE_checksum = 0; 467 GRPFILE_checksum_half_word = 0; 468} 469 470/*********************************************************************** 471 * 472 * GRPFILE_GetChecksum 473 */ 474 475static UINT16 GRPFILE_GetChecksum(void) 476{ 477 return GRPFILE_checksum; 478} 479 480/*********************************************************************** 481 * 482 * GRPFILE_WriteWithChecksum 483 * 484 * Looks crazier than it is: 485 * 486 * chksum = 0; 487 * chksum = cksum - 1. word; 488 * chksum = cksum - 2. word; 489 * ... 490 * 491 * if (filelen is even) 492 * great I'm finished 493 * else 494 * ignore last byte 495 */ 496 497static UINT GRPFILE_WriteWithChecksum(HFILE file, LPCSTR str, UINT size) 498{ 499 UINT i; 500 if (GRPFILE_checksum_half_word) { 501 GRPFILE_checksum -= GRPFILE_checksum_last_byte; 502 } 503 for (i=0; i < size; i++) { 504 if (GRPFILE_checksum_half_word) { 505 GRPFILE_checksum -= str[i] << 8; 506 } else { 507 GRPFILE_checksum -= str[i]; 508 } 509 GRPFILE_checksum_half_word ^= 1; 510 } 511 512 if (GRPFILE_checksum_half_word) { 513 GRPFILE_checksum_last_byte = str[size-1]; 514 GRPFILE_checksum += GRPFILE_checksum_last_byte; 515 } 516 517 return _lwrite(file, str, size); 518} 519 520 521/*********************************************************************** 522 * 523 * GRPFILE_DoWriteGroupFile 524 */ 525 526static BOOL GRPFILE_DoWriteGroupFile(HFILE file, PROGGROUP *group) 527{ 528 CHAR buffer[34]; 529 HLOCAL hProgram; 530 INT NumProg, Title, Progs, Icons, Extension; 531 INT CurrProg, CurrIcon, nCmdShow, ptr, seqnum; 532 533 UINT sizeAnd, sizeXor; 534 535 BOOL need_extension; 536 LPCSTR lpszTitle = LocalLock(group->hName); 537 538 UINT16 checksum; 539 540 GRPFILE_InitChecksum(); 541 542 /* Calculate offsets */ 543 NumProg = 0; 544 Icons = 0; 545 Extension = 0; 546 need_extension = FALSE; 547 hProgram = group->hPrograms; 548 while(hProgram) 549 { 550 PROGRAM *program = LocalLock(hProgram); 551 LPCSTR lpszWorkDir = LocalLock(program->hWorkDir); 552 553 NumProg++; 554 GRPFILE_CalculateSizes(program, &Icons, &Extension, &sizeAnd, &sizeXor); 555 556 /* Set a flag if an extension is needed */ 557 if (lpszWorkDir[0] || program->nHotKey || 558 program->nCmdShow != SW_SHOWNORMAL) need_extension = TRUE; 559 560 hProgram = program->hNext; 561 } 562 Title = 34 + NumProg * 2; 563 Progs = Title + strlen(lpszTitle) + 1; 564 Icons += Progs; 565 Extension += Icons; 566 567 /* Header */ 568 buffer[0] = 'P'; 569 buffer[1] = 'M'; 570 buffer[2] = 'C'; 571 buffer[3] = 'C'; 572 573 PUT_SHORT(buffer, 4, 0); /* Checksum zero for now, written later */ 574 PUT_SHORT(buffer, 6, Extension); 575 /* Update group->nCmdShow */ 576 if (IsIconic(group->hWnd)) nCmdShow = SW_SHOWMINIMIZED; 577 else if (IsZoomed(group->hWnd)) nCmdShow = SW_SHOWMAXIMIZED; 578 else nCmdShow = SW_SHOWNORMAL; 579 PUT_SHORT(buffer, 8, nCmdShow); 580 PUT_SHORT(buffer, 10, group->x); 581 PUT_SHORT(buffer, 12, group->y); 582 PUT_SHORT(buffer, 14, group->width); 583 PUT_SHORT(buffer, 16, group->height); 584 PUT_SHORT(buffer, 18, group->iconx); 585 PUT_SHORT(buffer, 20, group->icony); 586 PUT_SHORT(buffer, 22, Title); 587 PUT_SHORT(buffer, 24, 0x0020); /* unknown */ 588 PUT_SHORT(buffer, 26, 0x0020); /* unknown */ 589 PUT_SHORT(buffer, 28, 0x0108); /* unknown */ 590 PUT_SHORT(buffer, 30, 0x0000); /* unknown */ 591 PUT_SHORT(buffer, 32, NumProg); 592 593 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 34)) return FALSE; 594 595 /* Program table */ 596 CurrProg = Progs; 597 CurrIcon = Icons; 598 hProgram = group->hPrograms; 599 while(hProgram) 600 { 601 PROGRAM *program = LocalLock(hProgram); 602 603 PUT_SHORT(buffer, 0, CurrProg); 604 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 2)) 605 return FALSE; 606 607 GRPFILE_CalculateSizes(program, &CurrProg, &CurrIcon, &sizeAnd, &sizeXor); 608 hProgram = program->hNext; 609 } 610 611 /* Title */ 612 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszTitle, strlen(lpszTitle) + 1)) 613 return FALSE; 614 615 /* Program entries */ 616 CurrProg = Progs; 617 CurrIcon = Icons; 618 hProgram = group->hPrograms; 619 while(hProgram) 620 { 621 PROGRAM *program = LocalLock(hProgram); 622 LPCSTR Name = LocalLock(program->hName); 623 LPCSTR CmdLine = LocalLock(program->hCmdLine); 624 LPCSTR IconFile = LocalLock(program->hIconFile); 625 INT next_prog = CurrProg; 626 INT next_icon = CurrIcon; 627 628 GRPFILE_CalculateSizes(program, &next_prog, &next_icon, &sizeAnd, &sizeXor); 629 PUT_SHORT(buffer, 0, program->x); 630 PUT_SHORT(buffer, 2, program->y); 631 PUT_SHORT(buffer, 4, program->nIconIndex); 632 PUT_SHORT(buffer, 6, 0x048c); /* unknown */ 633 PUT_SHORT(buffer, 8, sizeXor); 634 PUT_SHORT(buffer, 10, sizeAnd * 8); 635 PUT_SHORT(buffer, 12, CurrIcon); 636 PUT_SHORT(buffer, 14, CurrIcon + 12 + sizeAnd); 637 PUT_SHORT(buffer, 16, CurrIcon + 12); 638 ptr = CurrProg + 24; 639 PUT_SHORT(buffer, 18, ptr); 640 ptr += strlen(Name) + 1; 641 PUT_SHORT(buffer, 20, ptr); 642 ptr += strlen(CmdLine) + 1; 643 PUT_SHORT(buffer, 22, ptr); 644 645 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 24) || 646 (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, Name, strlen(Name) + 1) || 647 (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, CmdLine, strlen(CmdLine) + 1) || 648 (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, IconFile, strlen(IconFile) + 1)) 649 return FALSE; 650 651 CurrProg = next_prog; 652 CurrIcon = next_icon; 653 hProgram = program->hNext; 654 } 655 656 /* Icons */ 657#if 0 /* FIXME: this is broken anyway */ 658 hProgram = group->hPrograms; 659 while(hProgram) 660 { 661 PROGRAM *program = LocalLock(hProgram); 662 CURSORICONINFO *iconinfo = LocalLock(program->hIcon); 663 LPVOID XorBits, AndBits; 664 INT sizeXor = iconinfo->nHeight * iconinfo->nWidthBytes; 665 INT sizeAnd = iconinfo->nHeight * ((iconinfo->nWidth + 15) / 16 * 2); 666 /* DumpIcon16(LocalLock(program->hIcon), 0, &XorBits, &AndBits);*/ 667 668 PUT_SHORT(buffer, 0, iconinfo->ptHotSpot.x); 669 PUT_SHORT(buffer, 2, iconinfo->ptHotSpot.y); 670 PUT_SHORT(buffer, 4, iconinfo->nWidth); 671 PUT_SHORT(buffer, 6, iconinfo->nHeight); 672 PUT_SHORT(buffer, 8, iconinfo->nWidthBytes); 673 buffer[10] = iconinfo->bPlanes; 674 buffer[11] = iconinfo->bBitsPerPixel; 675 676 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 12) || 677 (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, AndBits, sizeAnd) || 678 (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, XorBits, sizeXor)) return FALSE; 679 680 hProgram = program->hNext; 681 } 682#endif 683 684 if (need_extension) 685 { 686 /* write `PMCC' extension */ 687 PUT_SHORT(buffer, 0, 0x8000); 688 PUT_SHORT(buffer, 2, 0xffff); 689 PUT_SHORT(buffer, 4, 0x000a); 690 buffer[6] = 'P', buffer[7] = 'M'; 691 buffer[8] = 'C', buffer[9] = 'C'; 692 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 10)) 693 return FALSE; 694 695 seqnum = 0; 696 hProgram = group->hPrograms; 697 while(hProgram) 698 { 699 PROGRAM *program = LocalLock(hProgram); 700 LPCSTR lpszWorkDir = LocalLock(program->hWorkDir); 701 702 /* Working directory */ 703 if (lpszWorkDir[0]) 704 { 705 PUT_SHORT(buffer, 0, 0x8101); 706 PUT_SHORT(buffer, 2, seqnum); 707 PUT_SHORT(buffer, 4, 7 + strlen(lpszWorkDir)); 708 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6) || 709 (UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszWorkDir, strlen(lpszWorkDir) + 1)) 710 return FALSE; 711 } 712 713 /* Hot key */ 714 if (program->nHotKey) 715 { 716 PUT_SHORT(buffer, 0, 0x8102); 717 PUT_SHORT(buffer, 2, seqnum); 718 PUT_SHORT(buffer, 4, 8); 719 PUT_SHORT(buffer, 6, program->nHotKey); 720 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE; 721 } 722 723 /* Show command */ 724 if (program->nCmdShow) 725 { 726 PUT_SHORT(buffer, 0, 0x8103); 727 PUT_SHORT(buffer, 2, seqnum); 728 PUT_SHORT(buffer, 4, 8); 729 PUT_SHORT(buffer, 6, program->nCmdShow); 730 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE; 731 } 732 733 seqnum++; 734 hProgram = program->hNext; 735 } 736 737 /* Write `End' extension */ 738 PUT_SHORT(buffer, 0, 0xffff); 739 PUT_SHORT(buffer, 2, 0xffff); 740 PUT_SHORT(buffer, 4, 0x0000); 741 if ((UINT)HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6)) return FALSE; 742 } 743 744 checksum = GRPFILE_GetChecksum(); 745 _llseek(file, 4, SEEK_SET); 746 PUT_SHORT(buffer, 0, checksum); 747 _lwrite(file, buffer, 2); 748 749 return TRUE; 750} 751 752#endif