|
|
1.1 ! root 1: /************************************************************* ! 2: ! 3: This module contains subroutines for nead.c that specifically ! 4: deal with the manipulation of EAs. ! 5: ! 6: Procedures in this file: ! 7: AddEA() Handles the Add button press ! 8: QueryEAs() Reads in all the EAs associated with a file ! 9: CheckEAIntegrity() Checks an EA buffer to see if it is valid ! 10: Free_FEAList() Deallocates memory associated with EA list ! 11: LookupEAType() Gets an offset into table for an EA type ! 12: DeleteCurEA() Deletes the highlighted EA ! 13: CurEAType() Returns EA Type given a HoldFEA ptr ! 14: GetUSHORT() Returns nth USHORT in ->aValue ! 15: WriteEAs() Updates EAs state on the disk ! 16: EditEAValues() Handles editing a given EA (also m-m EAs) ! 17: EAExists() Determines if the given EA Name exists ! 18: ChangeName() Handles the change of an EA's name ! 19: MultiTypeIndex() Gets a specific field in a m-m structure ! 20: EAValueString() Returns a representational string for an EA ! 21: MultiAdd() Handles addition of a field for m-m ! 22: ! 23: **************************************************************/ ! 24: ! 25: #include "nead.h" ! 26: ! 27: /************ External GLOBALS *******************************/ ! 28: ! 29: extern CHAR szFileName[CCHMAXPATH]; ! 30: extern CHAR szEAName[MAXEANAME+1]; ! 31: extern USHORT usRetEAType; ! 32: extern BOOL FILE_ISOPEN; ! 33: extern BOOL FILE_CHANGED; ! 34: extern BOOL COMMAND_LINE_FILE; ! 35: extern CHAR *pAlloc,*szEditBuf,*szAscii,*szScratch; ! 36: extern HOLDFEA *pHoldFEA; ! 37: extern DELETELIST *pDelList; ! 38: extern EADATA ConvTable[EATABLESIZE]; ! 39: ! 40: /*************************************************************/ ! 41: ! 42: ! 43: /* ! 44: * Function name: AddEA() ! 45: * ! 46: * Parameters: hwnd which is the current window handle. ! 47: * ! 48: * Returns: TRUE iff the EA is successfully added. ! 49: * ! 50: * Purpose: This routine handles the addition of a new EA to the linked list. ! 51: * ! 52: * Usage/Warnings: Routine does NOT do full memory error trapping and the ! 53: * insert message to the l-box is not error checked. ! 54: * ! 55: * Calls: EditEAValue() ! 56: */ ! 57: ! 58: BOOL AddEA(HWND hwnd) ! 59: { ! 60: HOLDFEA *pFEA=pHoldFEA; /* Points to the beginning of the EA list */ ! 61: HOLDFEA *pNewFEA; /* Used to temporarily hold the new EA */ ! 62: PASSDATA PData; ! 63: ! 64: if(!FILE_ISOPEN) ! 65: return(FALSE); ! 66: ! 67: if(!WinDlgBox(HWND_DESKTOP, /* get new EA name and type */ ! 68: hwnd, ! 69: AddEAProc, ! 70: NULL, ! 71: IDD_ADDEA, ! 72: NULL)) ! 73: return(FALSE); /* they said cancel */ ! 74: ! 75: GetMem((PPVOID)&pNewFEA, sizeof(HOLDFEA)); /* Allocate space for new EA struct */ ! 76: ! 77: pNewFEA->cbName = (CHAR) strlen(szEAName); /* Fill in new structure */ ! 78: pNewFEA->cbValue= 0; ! 79: pNewFEA->fEA = 0; /* Need bit NOT set */ ! 80: ! 81: GetMem((PPVOID)&pNewFEA->szName, pNewFEA->cbName+1); /* Name returned in szEAName */ ! 82: strcpy(pNewFEA->szName,strupr(szEAName)); ! 83: pNewFEA->aValue = NULL; ! 84: pNewFEA->next = NULL; ! 85: ! 86: if(pHoldFEA == NULL) /* It's the first EA for the file */ ! 87: { ! 88: pHoldFEA = pNewFEA; ! 89: } ! 90: else /* Add EA to the end of the linked list */ ! 91: { ! 92: while(pFEA->next) ! 93: pFEA = pFEA->next; ! 94: pFEA->next = pNewFEA; ! 95: } ! 96: PData.Point = (CHAR *) pNewFEA; /* Setup user data for call */ ! 97: PData.cbMulti = 0; /* to edit of the name and */ ! 98: PData.usMultiOffset = 0; /* EA Value */ ! 99: ! 100: if(!EditEAValue(hwnd,&PData)) /* They canceled the edit */ ! 101: { ! 102: if(pFEA) /* It's not the only EA */ ! 103: pFEA->next = NULL; /* Disconnect the partial new EA */ ! 104: else ! 105: pHoldFEA = NULL; /* The new EA was the first one */ ! 106: ! 107: FreeMem(pNewFEA->szName); ! 108: FreeMem(pNewFEA); ! 109: ! 110: return(FALSE); ! 111: } ! 112: ! 113: WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM, /* Insert name in L-Box */ ! 114: MPFROM2SHORT(LIT_END,0), ! 115: MPFROMP(pNewFEA->szName)); ! 116: ! 117: return(TRUE); ! 118: } ! 119: ! 120: ! 121: /* ! 122: * Function name: QueryEAs() ! 123: * ! 124: * Parameters: hwnd which is the current window handle. ! 125: * pszPath points to the path of the file to grab EAs from. ! 126: * ! 127: * Returns: TRUE iff it successfully reads in the EAs. Upon exit, global ! 128: * pHoldFEA points to a linked list of the EAs for the current file. ! 129: * ! 130: * Purpose: Call DOS to Query a file's EA names and values. ! 131: * ! 132: * Usage/Warnings: Routine does NOT do full memory error trapping. ! 133: * NOTE: This routine does NOT prevent other processes ! 134: * from accessing the file's EAs while it is reading them ! 135: * in, or while the program is editing them. ! 136: * ! 137: * Calls: Free_FEAList(), CheckEAIntegrity() ! 138: */ ! 139: ! 140: BOOL QueryEAs(CHAR *pszPath) ! 141: { ! 142: CHAR *pAlloc; /* Holds the FEA struct returned by DosEnumAttribute */ ! 143: /* also used to create the GEALIST for DosQPathInfo */ ! 144: CHAR *pBigAlloc; /* Temp buffer to hold each EA as it is read in */ ! 145: USHORT cbBigAlloc; /* Size of buffer */ ! 146: ! 147: ULONG ulEntryNum = 1; /* count of current EA to read (1-relative) */ ! 148: ULONG ulEnumCnt; /* Number of EAs for Enum to return, always 1 */ ! 149: ! 150: HOLDFEA *pLastIn; /* Points to last EA added, so new EA can link */ ! 151: HOLDFEA *pNewFEA; /* Struct to build the new EA in */ ! 152: ! 153: FEA *pFEA; /* Used to read from Enum's return buffer */ ! 154: GEALIST *pGEAList; /* Ptr used to set up buffer for DosQPathInfo call */ ! 155: EAOP eaopGet; /* Used to call DosQPathInfo */ ! 156: ! 157: GetMem((PPVOID)&pAlloc, MAX_GEA); /* Allocate enough room for any GEA List */ ! 158: pFEA = (FEA *) pAlloc; /* pFEA always uses pAlloc buffer */ ! 159: ! 160: pHoldFEA = NULL; /* Reset the pointer for the EA linked list */ ! 161: ! 162: while(TRUE) /* Loop continues until there are no more EAs */ ! 163: { ! 164: ulEnumCnt = 1; /* Only want to get one EA at a time */ ! 165: if(DosEnumAttribute(Ref_ASCIIZ, /* Read into pAlloc Buffer */ ! 166: pszPath, /* Note that this does not */ ! 167: ulEntryNum, /* get the aValue field, */ ! 168: pAlloc, /* so DosQPathInfo must be */ ! 169: MAX_GEA, /* called to get it. */ ! 170: &ulEnumCnt, ! 171: (LONG) GetInfoLevel1)) ! 172: break; /* There was some sort of error */ ! 173: ! 174: if(ulEnumCnt != 1) /* All the EAs have been read */ ! 175: break; ! 176: ! 177: ulEntryNum++; ! 178: ! 179: GetMem((PPVOID)&pNewFEA, sizeof(HOLDFEA)); ! 180: ! 181: if (pNewFEA == NULL) /* Out of memory */ ! 182: { ! 183: FreeMem(pAlloc); ! 184: Free_FEAList(pHoldFEA,pDelList); ! 185: return (FALSE); ! 186: } ! 187: ! 188: pNewFEA->cbName = pFEA->cbName; /* Fill in the HoldFEA structure */ ! 189: pNewFEA->cbValue= pFEA->cbValue; ! 190: pNewFEA->fEA = pFEA->fEA; ! 191: pNewFEA->next = NULL; ! 192: ! 193: GetMem((PPVOID)&pNewFEA->szName, pFEA->cbName +1); /* Allocate for 2 arrays */ ! 194: GetMem((PPVOID)&pNewFEA->aValue, pFEA->cbValue); ! 195: ! 196: if (!pNewFEA->szName || !pNewFEA->aValue) /* Out of memory */ ! 197: { ! 198: if(pNewFEA->szName) ! 199: FreeMem(pNewFEA->szName); ! 200: if(pNewFEA->aValue) ! 201: FreeMem(pNewFEA->aValue); ! 202: ! 203: FreeMem(pAlloc); ! 204: FreeMem(pNewFEA); ! 205: ! 206: Free_FEAList(pHoldFEA,pDelList); ! 207: return (FALSE); ! 208: } ! 209: strcpy(pNewFEA->szName,pAlloc+sizeof(FEA)); /* Copy in EA Name */ ! 210: ! 211: cbBigAlloc = sizeof(FEALIST) + pNewFEA->cbName+1 + pNewFEA->cbValue; ! 212: GetMem((PPVOID)&pBigAlloc, cbBigAlloc); ! 213: if (pBigAlloc == NULL) ! 214: { ! 215: FreeMem(pNewFEA->szName); ! 216: FreeMem(pNewFEA->aValue); ! 217: FreeMem(pAlloc); ! 218: FreeMem(pNewFEA); ! 219: Free_FEAList(pHoldFEA,pDelList); ! 220: return (FALSE); ! 221: } ! 222: ! 223: pGEAList = (GEALIST *) pAlloc; /* Set up GEAList structure */ ! 224: ! 225: pGEAList->cbList = sizeof(GEALIST) + pNewFEA->cbName; /* +1 for NULL */ ! 226: pGEAList->list[0].cbName = pNewFEA->cbName; ! 227: strcpy(pGEAList->list[0].szName,pNewFEA->szName); ! 228: ! 229: eaopGet.fpGEAList = (GEALIST FAR *) pAlloc; ! 230: eaopGet.fpFEAList = (FEALIST FAR *) pBigAlloc; ! 231: ! 232: eaopGet.fpFEAList->cbList = cbBigAlloc; ! 233: ! 234: DosQPathInfo(pszPath, /* Get the complete EA info */ ! 235: GetInfoLevel3, ! 236: (PVOID) &eaopGet, ! 237: sizeof(EAOP)); ! 238: memcpy(pNewFEA->aValue, /* Copy the value to HoldFEA */ ! 239: pBigAlloc+sizeof(FEALIST)+pNewFEA->cbName+1, ! 240: pNewFEA->cbValue); ! 241: ! 242: FreeMem(pBigAlloc); /* Release the temp Enum buffer */ ! 243: ! 244: if(!CheckEAIntegrity(pNewFEA->aValue,pNewFEA->cbValue)) /* Bad EA */ ! 245: { ! 246: FreeMem(pNewFEA->szName); ! 247: FreeMem(pNewFEA->aValue); ! 248: FreeMem(pNewFEA); ! 249: continue; /* Don't add this EA to linked list */ ! 250: } ! 251: ! 252: if(pHoldFEA == NULL) /* If first EA, set pHoldFEA */ ! 253: pHoldFEA = pNewFEA; ! 254: else /* Otherwise, add to end of list */ ! 255: pLastIn->next = pNewFEA; ! 256: ! 257: pLastIn = pNewFEA; /* Update the end of the list */ ! 258: } ! 259: FreeMem(pAlloc); /* Free up the GEA buf for DosEnum */ ! 260: return (TRUE); ! 261: } ! 262: ! 263: ! 264: /* ! 265: * Function name: CheckEAIntegrity() ! 266: * ! 267: * Parameters: aBuf points to the buffer to check for a valid EA. ! 268: * cbBuf is the allocated length of aBuf. ! 269: * ! 270: * Returns: TRUE iff the buffer is a valid EA structure. ! 271: * ! 272: * Purpose: This routine checks the integrity of the passed EA buffer by ! 273: * seeing if there are any non-standard EA types, or bad data that ! 274: * isn't sized correctly. ! 275: * ! 276: * Usage/Warnings: Routine uses MultiTypeIndex() to check m-m type EAs ! 277: * since they are potentially recursive. However, this ! 278: * may not be a good idea if the m-m EA is severly ! 279: * corrupted because it may cause MTI() to attempt a read ! 280: * from protected memory. Routine does NOT modify the ! 281: * buffer under any circumstance. ! 282: * ! 283: * Calls: MultiTypeIndex() ! 284: */ ! 285: ! 286: BOOL CheckEAIntegrity(CHAR *aBuf,USHORT cbBuf) ! 287: { ! 288: USHORT *pusPtr = (USHORT *) aBuf; ! 289: USHORT usOffset; ! 290: CHAR *aEndPtr; ! 291: ! 292: usOffset = LookupEAType(*pusPtr); /* Get the EA type */ ! 293: ! 294: switch(ConvTable[usOffset].usFldType) ! 295: { ! 296: case IDD_LPDATA: ! 297: pusPtr++; ! 298: if(*pusPtr + 2*sizeof(USHORT) == cbBuf) ! 299: return TRUE; ! 300: else ! 301: return FALSE; ! 302: ! 303: case IDD_MULTILIST: ! 304: if(*pusPtr == EA_MVMT) ! 305: { ! 306: pusPtr += 2; ! 307: ! 308: /* This checks where the end of the m-m list ends to determine ! 309: the size of the EA. This is probably not good if the EA is ! 310: badly corrupted and it points to protected memory */ ! 311: ! 312: aEndPtr = MultiTypeIndex(aBuf,*pusPtr); ! 313: if(aEndPtr - aBuf == cbBuf) ! 314: return TRUE; ! 315: else ! 316: return FALSE; ! 317: } ! 318: else /* Single type, multi-value is not yet implemented */ ! 319: { ! 320: return TRUE; ! 321: } ! 322: default: ! 323: return FALSE; ! 324: } ! 325: return TRUE; ! 326: } ! 327: ! 328: ! 329: /* ! 330: * Function name: Free_FEAList() ! 331: * ! 332: * Parameters: pFEA points to the beginning of the linked list to be freed. ! 333: * pDList points to the beginning of the deleted linked list. ! 334: * ! 335: * Returns: VOID. The two linked lists passed in are cleaned out though. ! 336: * ! 337: * Purpose: This routine frees up the current list of EAs by deallocating ! 338: * the space used by the szName and aValue fields, then deallocating ! 339: * the HoldFEA struct. Next, it deletes the EAName space, then the ! 340: * DeleteList structure. ! 341: * ! 342: * Usage/Warnings: Note that NEAD always passes in pHoldFEA and pDelList ! 343: * which is unnecessary since they are global pointers; ! 344: * however, this is done to make the routine more flexible ! 345: * by allowing multiple linked lists to exist. ! 346: * ! 347: * Calls: ! 348: */ ! 349: ! 350: VOID Free_FEAList(HOLDFEA *pFEA,DELETELIST *pDList) ! 351: { ! 352: HOLDFEA *next; /* Holds the next field since we free the structure */ ! 353: /* before reading the current next field */ ! 354: DELETELIST *Dnext; /* Same purpose as *next */ ! 355: ! 356: while(pFEA) ! 357: { ! 358: next = pFEA->next; ! 359: if(pFEA->szName) /* Free if non-NULL name */ ! 360: FreeMem(pFEA->szName); ! 361: if(pFEA->aValue) /* Free if non-NULL value */ ! 362: FreeMem(pFEA->aValue); ! 363: ! 364: FreeMem(pFEA); /* Free HoldFEA struct */ ! 365: pFEA = next; ! 366: } ! 367: ! 368: while(pDList) ! 369: { ! 370: Dnext = pDList->next; ! 371: if(pDList->EAName) ! 372: FreeMem(pDList->EAName); ! 373: FreeMem(pDList); ! 374: pDList = Dnext; ! 375: } ! 376: } ! 377: ! 378: ! 379: /* ! 380: * Function name: LookupEAType() ! 381: * ! 382: * Parameters: usType is tye EA type to be looked up. ! 383: * ! 384: * Returns: An offset into the ConvTable to the appropriate entry. If no ! 385: * match is found, the return value points to the last entry, ! 386: * non-conventional format. ! 387: * ! 388: * Purpose: This routine takes EA type and returns an offset into ConvTable ! 389: * which points to an entry that describes the type passed in. ! 390: * ! 391: * Usage/Warnings: ! 392: * ! 393: * Calls: ! 394: */ ! 395: ! 396: USHORT LookupEAType(USHORT usType) ! 397: { ! 398: USHORT cnt; ! 399: ! 400: for(cnt=0;cnt<EATABLESIZE-1;cnt++) ! 401: if(ConvTable[cnt].usPrefix == usType) ! 402: return(cnt); ! 403: return(cnt); ! 404: } ! 405: ! 406: ! 407: /* ! 408: * Function name: DeleteCurEA() ! 409: * ! 410: * Parameters: hwnd is the current window handle. ! 411: * ! 412: * Returns: VOID. Removes one item from global pHoldFEA list and adds one ! 413: * to global pDelList. ! 414: * ! 415: * Purpose: This routine removes in memory the currently highlighted EA from ! 416: * the EA list. It places the deleted EA in the global pDelList ! 417: * linked list. ! 418: * ! 419: * Usage/Warnings: The memory allocation routines are NOT fully error trapped. ! 420: * ! 421: * Calls: GetCurFEA() ! 422: */ ! 423: ! 424: VOID DeleteCurEA(HWND hwnd) ! 425: { ! 426: HOLDFEA *pFEA,*pFEAPrev; ! 427: DELETELIST *pDL,*pDLcnt; /* Utility ptrs for manipulating the Del list */ ! 428: LONG lOffset; ! 429: ! 430: pFEA = GetCurFEA(hwnd,pHoldFEA); /* Gets a pointer to item to delete */ ! 431: if (pFEA == NULL) ! 432: return; ! 433: ! 434: /* These two allocations should be checked for out of memory */ ! 435: GetMem((PPVOID)&pDL, sizeof(DELETELIST)); /* Add Name to Delete List */ ! 436: GetMem((PPVOID)&pDL->EAName, pFEA->cbName+1); ! 437: strcpy(pDL->EAName,pFEA->szName); ! 438: pDL->next = NULL; ! 439: ! 440: if(pDelList == NULL) /* The del list was previously empty */ ! 441: pDelList = pDL; ! 442: else /* tack name onto the end of the list */ ! 443: { ! 444: pDLcnt = pDelList; ! 445: while(pDLcnt->next) ! 446: pDLcnt = pDLcnt->next; ! 447: pDLcnt->next = pDL; ! 448: } ! 449: ! 450: lOffset = (LONG) WinSendDlgItemMsg(hwnd, IDD_LBOX, ! 451: LM_QUERYSELECTION,0,0); ! 452: WinSendDlgItemMsg(hwnd, IDD_LBOX, ! 453: LM_DELETEITEM,MPFROMSHORT((SHORT) lOffset),0L); ! 454: ! 455: if(lOffset<1) /* Remove pFEA from the linked list */ ! 456: { ! 457: pHoldFEA = pFEA->next; ! 458: } ! 459: else ! 460: { ! 461: pFEAPrev = pHoldFEA; ! 462: ! 463: while(--lOffset) /* Find previous EA */ ! 464: pFEAPrev = pFEAPrev->next; ! 465: ! 466: pFEAPrev->next = pFEA->next; ! 467: } ! 468: ! 469: FreeMem(pFEA->szName); /* Release the memory */ ! 470: FreeMem(pFEA->aValue); ! 471: FreeMem(pFEA); ! 472: ! 473: FILE_CHANGED = TRUE; ! 474: } ! 475: ! 476: ! 477: /* ! 478: * Function name: CurEAType() ! 479: * ! 480: * Parameters: pFEA points to the FEA struct to use. ! 481: * ! 482: * Returns: The EA type. ! 483: * ! 484: * Purpose: Given an EA structure, this routine returns the Type of the EA ! 485: * which resides in the first USHORT of the aValue member. ! 486: * This function is the same as GetUSHORT(pFEA,0) ! 487: * ! 488: * Usage/Warnings: Assumes a valid HoldFEA struct. ! 489: * ! 490: * Calls: ! 491: */ ! 492: ! 493: USHORT CurEAType(HOLDFEA *pFEA) /* Same as GetUSHORT(,0); */ ! 494: { ! 495: USHORT *pusType; /* EA Type is stored in first USHORT of aValue field */ ! 496: ! 497: pusType = (USHORT *) pFEA->aValue; ! 498: return(*pusType); ! 499: } ! 500: ! 501: ! 502: /* ! 503: * Function name: GetUSHORT() ! 504: * ! 505: * Parameters: pFEA points to the FEA struct to use. ! 506: * index is an offset of the USHORT to be returned ! 507: * ! 508: * Returns: The appropriate USHORT from the aValue field ! 509: * ! 510: * Purpose: This routine returns the nth USHORT value in the aValue member ! 511: * of pFEA using index as the offset. ! 512: * ! 513: * Usage/Warnings: Assumes a valid HoldFEA struct and that index doesn't ! 514: * point outside the aValue buffer. ! 515: * ! 516: * Calls: ! 517: */ ! 518: ! 519: USHORT GetUSHORT(HOLDFEA *pFEA,USHORT index) ! 520: { ! 521: USHORT *pusType; ! 522: ! 523: pusType = (USHORT *) pFEA->aValue; ! 524: while(index-- > 0) ! 525: pusType++; ! 526: return(*pusType); ! 527: } ! 528: ! 529: ! 530: /* ! 531: * Function name: WriteEAs() ! 532: * ! 533: * Parameters: hwnd is the current window handle used only by memory ! 534: * allocation error handling. ! 535: * ! 536: * Returns: VOID. But cleans out the pDelList linked list. ! 537: * ! 538: * Purpose: This routine updates the EAs on disk to reflect their current ! 539: * condition in memory. First, all EAs in the delete list are ! 540: * removed from the disk, then all EAs in the pHoldFEA list are ! 541: * written out to disk. ! 542: * ! 543: * Usage/Warnings: NOTE: This routine is not bulletproof as it does not get ! 544: * exclusive access to the file EAs, nor does it handle out ! 545: * of disk space sort of errors. Also, memory fetches are ! 546: * not fully error trapped. ! 547: * ! 548: * Calls: ! 549: */ ! 550: ! 551: VOID WriteEAs() ! 552: { ! 553: DELETELIST *pDL = pDelList,*pDLnext; ! 554: HOLDFEA *pHFEA= pHoldFEA; ! 555: EAOP eaopWrite; ! 556: CHAR aBuf[MAX_GEA],*aPtr; ! 557: FEA *pFEA = (FEA *) &aBuf[sizeof(ULONG)]; ! 558: USHORT usRet,usMemNeeded; ! 559: ULONG *pulPtr=(ULONG *) aBuf; /* Initally points to top of FEALIST */ ! 560: ! 561: if(!FILE_ISOPEN || !FILE_CHANGED) /* Don't write unless it's necessary */ ! 562: return; ! 563: ! 564: eaopWrite.fpFEAList = (FEALIST FAR *) aBuf; /* Setup fields that won't */ ! 565: pFEA->fEA = 0; /* change for the delete */ ! 566: pFEA->cbValue = 0; /* calls to DosSetPathInfo */ ! 567: ! 568: while(pDL) /* Clean out all the deleted EA names */ ! 569: { ! 570: pFEA->cbName = (UCHAR) strlen(pDL->EAName); ! 571: *pulPtr = sizeof(FEALIST) + pFEA->cbName+1; /* +1 for NULL */ ! 572: strcpy(aBuf+sizeof(FEALIST),pDL->EAName); ! 573: ! 574: usRet=DosSetPathInfo(szFileName, /* Delete EA's by saying cbValue=0 */ ! 575: SetInfoLevel2, ! 576: (PVOID) &eaopWrite, ! 577: (USHORT) sizeof(EAOP), ! 578: DSPI_WRTTHRU); ! 579: ! 580: pDLnext = pDL->next; /* Temp hold next pDL */ ! 581: FreeMem(pDL->EAName); /* Free up current Del struct */ ! 582: FreeMem(pDL); ! 583: pDL = pDLnext; /* Set pDL to saved value */ ! 584: } ! 585: pDelList = NULL; /* DelList is now empty */ ! 586: ! 587: while(pHFEA) /* Go through each HoldFEA */ ! 588: { ! 589: usMemNeeded = sizeof(FEALIST) + pHFEA->cbName+1 + pHFEA->cbValue; ! 590: GetMem((PPVOID)&aPtr, usMemNeeded); ! 591: ! 592: eaopWrite.fpFEAList = (FEALIST FAR *) aPtr; /* Fill in eaop struct */ ! 593: eaopWrite.fpFEAList->cbList = usMemNeeded; ! 594: ! 595: eaopWrite.fpFEAList->list[0].fEA = pHFEA->fEA; ! 596: eaopWrite.fpFEAList->list[0].cbName = pHFEA->cbName; ! 597: eaopWrite.fpFEAList->list[0].cbValue = pHFEA->cbValue; ! 598: ! 599: strcpy(aPtr + sizeof(FEALIST), pHFEA->szName); ! 600: memcpy(aPtr + sizeof(FEALIST) + pHFEA->cbName+1, ! 601: pHFEA->aValue, pHFEA->cbValue); ! 602: ! 603: usRet=DosSetPathInfo(szFileName, /* Write out the EA */ ! 604: SetInfoLevel2, ! 605: (PVOID) &eaopWrite, ! 606: (USHORT) sizeof(EAOP), ! 607: DSPI_WRTTHRU); ! 608: ! 609: FreeMem(aPtr); /* Free up the FEALIST struct */ ! 610: ! 611: pHFEA = pHFEA->next; ! 612: } ! 613: ! 614: FILE_CHANGED = FALSE; ! 615: } ! 616: ! 617: ! 618: /* ! 619: * Function name: EditEAValue() ! 620: * ! 621: * Parameters: hwnd is the current window handle. ! 622: * pPDat is a pointer to PassData which contains Edit EA info. ! 623: * ! 624: * Returns: TRUE iff the edit was successful. ! 625: * ! 626: * Purpose: This routine allows the entry/edit of an EA value. ! 627: * condition in memory. First, all EAs in the delete list are ! 628: * removed from the disk, then all EAs in the pHoldFEA list are ! 629: * written out to disk. ! 630: * ! 631: * Usage/Warnings: Expects the PassData structure to tell it the HoldFEA ! 632: * to edit, and if it is a subfield of a multi-multi EA, ! 633: * the rest of the PassData structure will be filled in ! 634: * to indicated which m-m is being edited. Note that if ! 635: * this is a new edit, usRetEAType is expected to be set ! 636: * to the proper EA type upon entry. NOTE: memory sizing ! 637: * requests are not fully error trapped. ! 638: * ! 639: * Calls: MultiTypeIndex(), ChangeName(), AsciiEditProc() (thru PM), ! 640: * MultiTypeProc() (thru PM). ! 641: */ ! 642: ! 643: BOOL EditEAValue(HWND hwnd, PASSDATA *pPDat) ! 644: { ! 645: USHORT usEAType; /* Holds the field type to be edited */ ! 646: USHORT *pusPtr; ! 647: USHORT usSize; /* Holds the delta difference of the old and new buffers */ ! 648: CHAR *szNew,*szTrash; /* Temporary pointers */ ! 649: PASSDATA PDat; ! 650: HOLDFEA *pFEA = (HOLDFEA *) pPDat->Point; /* The EA to be edited */ ! 651: ! 652: /* Determine the type of EA that will be edited */ ! 653: if(pPDat->cbMulti) /* It's a multi-type job */ ! 654: { ! 655: pusPtr = (USHORT *) MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset, ! 656: pPDat->usIndex); ! 657: usEAType = *pusPtr; ! 658: } ! 659: else if(pFEA->cbValue) /* It isn't a new EA name */ ! 660: { ! 661: pusPtr = (USHORT *) pFEA->aValue; ! 662: usEAType = *pusPtr; ! 663: } ! 664: else /* It's a new EA */ ! 665: { ! 666: usEAType = ConvTable[usRetEAType].usPrefix; ! 667: } ! 668: ! 669: PDat.Point = pFEA->szName; /* General setup for AsciiEditProc */ ! 670: PDat.usIndex = pPDat->cbMulti ? 1 : 0; /* =1 if there is a multi */ ! 671: PDat.fFlag = (BYTE) ((pFEA->fEA & 0x80) ? TRUE : FALSE); ! 672: ! 673: switch(usEAType) ! 674: { ! 675: case EA_ASCIIZ: ! 676: case EA_ASCIIZFN: ! 677: case EA_ASCIIZEA: ! 678: case EA_ASN1: ! 679: if(pPDat->cbMulti) /* It is a multi-type field */ ! 680: szAscii=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 681: pPDat->usIndex) ! 682: +sizeof(USHORT); ! 683: else if(pFEA->cbValue) /* There is a current value */ ! 684: szAscii=pFEA->aValue+sizeof(USHORT); ! 685: else /* It's a new EA */ ! 686: szAscii=NULL; ! 687: ! 688: ! 689: if(!WinDlgBox(HWND_DESKTOP, /* Do an ascii text edit */ ! 690: hwnd, ! 691: AsciiEditProc, ! 692: NULL, ! 693: IDD_ASCIIEDIT, ! 694: &PDat)) ! 695: return(FALSE); /* They said cancel */ ! 696: ! 697: if(PDat.fFlag) /* Handle the need/nice bit */ ! 698: PDat.fFlag = 0x80; ! 699: if(PDat.fFlag != (PDat.fFlag & 0x80)) ! 700: FILE_CHANGED = TRUE; ! 701: pFEA->fEA = (pFEA->fEA & 0x7f) | PDat.fFlag; ! 702: ! 703: if(stricmp(strupr(szEAName),pFEA->szName)) /* The name changed */ ! 704: ChangeName(pFEA,szEAName); ! 705: ! 706: if(pFEA->cbValue) /* There is a current value */ ! 707: { ! 708: if(!strcmp(szAscii,szScratch)) /* It hasn't changed */ ! 709: return(TRUE); ! 710: ! 711: if(pPDat->cbMulti) /* Do the whole thing here if m-m */ ! 712: { ! 713: usSize = strlen(szScratch)-strlen(szAscii); /* Change in size */ ! 714: ! 715: if(usSize > 0) /* The new string is longer */ ! 716: { ! 717: ResizeMem(pFEA->aValue, /* Enlarge the EA size */ ! 718: pFEA->cbValue, ! 719: pFEA->cbValue+usSize); ! 720: szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 721: pPDat->usIndex+1); ! 722: memmove(szTrash+usSize, /* Move end of EA to make room */ ! 723: szTrash, ! 724: pFEA->cbValue-(szTrash-pFEA->aValue)); ! 725: } ! 726: else if(usSize < 0) /* The new string is shorter */ ! 727: { ! 728: szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 729: pPDat->usIndex+1); ! 730: memmove(szTrash+usSize, /* Move back the end of the EA */ ! 731: szTrash, ! 732: pFEA->cbValue-(szTrash-pFEA->aValue)); ! 733: DosSetMem(pFEA->aValue, pFEA->cbValue+usSize, fPERM|PAG_COMMIT); ! 734: } ! 735: szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 736: pPDat->usIndex); ! 737: strcpy(szTrash+sizeof(USHORT),szScratch); /* Copy in new val */ ! 738: pFEA->cbValue+=usSize; /* Change buffer count */ ! 739: ! 740: return(FILE_CHANGED = TRUE); /* Done with m-m edit */ ! 741: } ! 742: else ! 743: { ! 744: FreeMem(pFEA->aValue); /* Release old Value mem */ ! 745: } ! 746: } ! 747: GetMem((PPVOID)&szNew, strlen(szScratch)+3); /* +3 for Type & NULL */ ! 748: pusPtr = (USHORT *) szNew; ! 749: *pusPtr= usEAType; /* Set type in new buffer */ ! 750: strcpy(szNew+2,szScratch); /* Copy in the new value */ ! 751: pFEA->aValue = szNew; /* Fix up the structure */ ! 752: pFEA->cbValue= strlen(szScratch)+3; ! 753: ! 754: return(FILE_CHANGED = TRUE); ! 755: ! 756: case EA_LPBINARY: ! 757: case EA_LPASCII: ! 758: case EA_LPMETAFILE: ! 759: if(pPDat->cbMulti) /* It is a multi-type field */ ! 760: { /* szTrash points to field to edit, pusPtr to the field length */ ! 761: szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 762: pPDat->usIndex); ! 763: pusPtr = (USHORT *) ((CHAR *) szTrash + sizeof(USHORT)); ! 764: usSize = *pusPtr; ! 765: if(usSize) /* It isn't a new EA */ ! 766: { ! 767: GetMem((PPVOID)&szAscii, usSize+1); /* Set up inital value for edit */ ! 768: memcpy(szAscii,szTrash+2*sizeof(USHORT),usSize); ! 769: szAscii[usSize]=NULL; ! 770: } ! 771: else /* No inital value */ ! 772: szAscii = NULL; ! 773: } ! 774: else if(pFEA->cbValue) ! 775: { ! 776: usSize=GetUSHORT(pFEA,1); /* Get size and set inital value */ ! 777: if(usSize) ! 778: { ! 779: GetMem((PPVOID)&szTrash, usSize+1); /* +1 for null */ ! 780: memcpy(szTrash,pFEA->aValue+4,usSize); ! 781: szTrash[usSize]=NULL; ! 782: szAscii=szTrash; ! 783: } ! 784: else ! 785: szAscii = NULL; ! 786: } ! 787: else ! 788: szAscii = NULL; ! 789: ! 790: if(!WinDlgBox(HWND_DESKTOP, /* Do an ascii text edit */ ! 791: hwnd, ! 792: AsciiEditProc, ! 793: NULL, ! 794: IDD_ASCIIEDIT, ! 795: &PDat)) ! 796: { /* Cancel, but check if memory needs to be freed before exit */ ! 797: if(pPDat->cbMulti || pFEA->cbValue) ! 798: if(szAscii) /* It's not NULL */ ! 799: FreeMem(szAscii); /* +1 for NULL */ ! 800: ! 801: return(FALSE); ! 802: } ! 803: ! 804: if(PDat.fFlag) /* Handle the need/nice bit */ ! 805: PDat.fFlag = 0x80; ! 806: if(PDat.fFlag != (PDat.fFlag & 0x80)) ! 807: FILE_CHANGED = TRUE; ! 808: pFEA->fEA = (pFEA->fEA & 0x7f) | PDat.fFlag; ! 809: ! 810: if(stricmp(strupr(szEAName),pFEA->szName)) /* The name changed */ ! 811: ChangeName(pFEA,szEAName); ! 812: ! 813: if(pFEA->cbValue) /* There is a current value */ ! 814: { ! 815: if(!strcmp(szAscii,szScratch)) /* It hasn't changed */ ! 816: { ! 817: if(szAscii) ! 818: FreeMem(szAscii); ! 819: return(TRUE); ! 820: } ! 821: if(szAscii) /* Free default value buffer */ ! 822: FreeMem(szAscii); ! 823: ! 824: if(pPDat->cbMulti) /* Do the whole thing here is multi-type */ ! 825: { ! 826: USHORT usDelta = strlen(szScratch) - usSize; /* Change in len */ ! 827: if(usDelta > 0) /* The new string is longer, resize first */ ! 828: { ! 829: ResizeMem(pFEA->aValue, pFEA->cbValue, pFEA->cbValue+usDelta); ! 830: szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 831: pPDat->usIndex+1); ! 832: memmove(szTrash+usDelta,szTrash, ! 833: pFEA->cbValue-(szTrash-pFEA->aValue)); ! 834: } ! 835: else if(usDelta < 0) /* move first, resize afterwards */ ! 836: { ! 837: szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 838: pPDat->usIndex+1); ! 839: memmove(szTrash+usDelta,szTrash, ! 840: pFEA->cbValue-(szTrash-pFEA->aValue)); ! 841: ResizeMem(pFEA->aValue, pFEA->cbValue+usDelta, fPERM|PAG_COMMIT); ! 842: } ! 843: szTrash=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 844: pPDat->usIndex); ! 845: memmove(szTrash+2*sizeof(USHORT),szScratch,strlen(szScratch)); ! 846: pusPtr = (USHORT *) ((CHAR *) szTrash + sizeof(USHORT)); ! 847: *pusPtr= strlen(szScratch); /* Set the length field */ ! 848: ! 849: ! 850: pFEA->cbValue += usDelta; /* Adjust struct len field */ ! 851: ! 852: return(FILE_CHANGED = TRUE); ! 853: } ! 854: ! 855: FreeMem(pFEA->aValue); /* Free up old value */ ! 856: } ! 857: GetMem((PPVOID)&szNew, strlen(szScratch)+4); /* Get space for new value */ ! 858: pusPtr = (USHORT *) szNew; ! 859: *pusPtr= usEAType; /* Set type field */ ! 860: pusPtr++; ! 861: *pusPtr= strlen(szScratch); /* Set length field */ ! 862: memcpy(szNew+4,szScratch,*pusPtr); /* Copy in new value */ ! 863: pFEA->aValue = szNew; /* Adjust pointers */ ! 864: pFEA->cbValue= strlen(szScratch)+4; /* +4 for type and LP cnt */ ! 865: ! 866: return(FILE_CHANGED = TRUE); ! 867: ! 868: case EA_MVMT: /* It's multi-value multi-type */ ! 869: if(pFEA->cbValue == 0) /* It's a new EA */ ! 870: { ! 871: GetMem((PPVOID)&pFEA->aValue, 3*sizeof(USHORT)); /* Allocate empty m-m EA */ ! 872: pFEA->cbValue = 3*sizeof(USHORT); ! 873: pusPtr = (USHORT *) pFEA->aValue; ! 874: *pusPtr = 0xffdf; /* Multi-value, multi-type */ ! 875: pusPtr+=2; /* Skip type, codepage */ ! 876: *pusPtr = 0; /* No fields initially */ ! 877: FILE_CHANGED = TRUE; ! 878: } ! 879: ! 880: /* Set up passed in data */ ! 881: if(pPDat->cbMulti) /* It's a multi-type job */ ! 882: { ! 883: szNew = MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 884: pPDat->usIndex); ! 885: szTrash = MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset, ! 886: pPDat->usIndex+1); ! 887: PDat.usMultiOffset = szNew - pFEA->aValue; ! 888: PDat.cbMulti = szTrash - szNew; ! 889: } ! 890: else ! 891: { ! 892: PDat.usMultiOffset = 0; ! 893: PDat.cbMulti = pFEA->cbValue; ! 894: } ! 895: PDat.Point = (CHAR *) pFEA; ! 896: ! 897: WinDlgBox(HWND_DESKTOP, /* Do the Multi-type edit */ ! 898: hwnd, ! 899: MultiTypeProc, ! 900: NULL, ! 901: IDD_MULTIBOX, ! 902: &PDat); ! 903: return(TRUE); ! 904: ! 905: } ! 906: } ! 907: ! 908: ! 909: /* ! 910: * Function name: EAExists() ! 911: * ! 912: * Parameters: szEAName points to the EA Name to check for. ! 913: * ! 914: * Returns: TRUE iff an EA with a name matching szEAName exists. ! 915: * ! 916: * Purpose: This routine goes through the linked list pointed to by global ! 917: * pHoldFEA and determines whether or not an EA of the passed name ! 918: * already exists. ! 919: * ! 920: * Usage/Warnings: The comparison is NOT case sensitive. ! 921: * ! 922: * Calls: ! 923: * ! 924: */ ! 925: ! 926: BOOL EAExists(CHAR *szEAName) ! 927: { ! 928: HOLDFEA *phFEA=pHoldFEA; ! 929: ! 930: while(phFEA) ! 931: { ! 932: if(!stricmp(szEAName,phFEA->szName)) ! 933: return(TRUE); ! 934: phFEA=phFEA->next; ! 935: } ! 936: return(FALSE); ! 937: } ! 938: ! 939: ! 940: /* ! 941: * Function name: ChangeName() ! 942: * ! 943: * Parameters: hwnd is the current window used for error messages. ! 944: * pFEA points to the current FEA. ! 945: * szName points to the new EA name. ! 946: * ! 947: * Returns: VOID. Fixes up the pFEA structure and global pDelList. ! 948: * ! 949: * Purpose: This routine copies the current EA Name to the delete list, then ! 950: * allocates a new space, copies the new name into it, and sets the ! 951: * FEA pointer to it. ! 952: * ! 953: * Usage/Warnings: NOTE: Not all the memory allocations are fully error ! 954: * trapped. ! 955: * ! 956: * Calls: ! 957: * ! 958: */ ! 959: ! 960: VOID ChangeName(HOLDFEA *pFEA,CHAR *szName) ! 961: { ! 962: CHAR *szTemp; ! 963: DELETELIST *pDL; ! 964: ! 965: GetMem((PPVOID)&szTemp, strlen(szName+1)); /* Allocate space for new name */ ! 966: if(!szTemp) ! 967: return; ! 968: ! 969: GetMem((PPVOID)&pDL, (USHORT) sizeof(DELETELIST)); /* Allocate a new delete struct */ ! 970: pDL->EAName = pFEA->szName; /* Fill in DeleteList struct */ ! 971: pDL->next = pDelList; ! 972: pDelList = pDL; ! 973: ! 974: strcpy(szTemp,szName); /* Copy name to permanent buffer */ ! 975: pFEA->szName = szTemp; /* Fix up struct */ ! 976: pFEA->cbName = (CHAR) strlen(szName); ! 977: ! 978: FILE_CHANGED = TRUE; ! 979: } ! 980: ! 981: ! 982: /* ! 983: * Function name: MultiTypeIndex() ! 984: * ! 985: * Parameters: pMulti points to the current m-m field. ! 986: * usIndex is the field the caller is interested in. ! 987: * ! 988: * Returns: a pointer to the field specified by the usIndex param. ! 989: * ! 990: * Purpose: This routine takes a pointer to a Multi-Multi data field and ! 991: * returns a pointer to the nth data field in this buffer. ! 992: * ! 993: * Usage/Warnings: NOTE: Memory bounds are not checked and a corrupt ! 994: * EA field could cause unspecified results. ! 995: * Recursively calls itself to handle nesting. Does not ! 996: * support multi-value single type fields. ! 997: * ! 998: * Calls: LookupEAType, MultiTypeIndex() ! 999: * ! 1000: */ ! 1001: ! 1002: CHAR *MultiTypeIndex(CHAR *pMulti, USHORT usIndex) ! 1003: { ! 1004: USHORT *pusPtr; ! 1005: USHORT usOffset; ! 1006: ! 1007: pMulti += 3*sizeof(USHORT); /* skip over 0xffdf, codepage, and field cnt */ ! 1008: ! 1009: while(usIndex--) /* loop to skip over correct # of flds */ ! 1010: { ! 1011: pusPtr = (USHORT *) pMulti; ! 1012: usOffset = LookupEAType(*pusPtr); /* Get offset of field type */ ! 1013: ! 1014: pMulti += sizeof(USHORT); /* Skip over the type field */ ! 1015: ! 1016: switch(ConvTable[usOffset].usFldType) ! 1017: { ! 1018: case IDD_ASCIIZ: ! 1019: while(*pMulti++); /* Increment to point after NULL */ ! 1020: break; ! 1021: ! 1022: case IDD_LPDATA: ! 1023: pusPtr = (USHORT *) pMulti; /* Get the length */ ! 1024: pMulti += *pusPtr + sizeof(USHORT); /* skip to end */ ! 1025: break; ! 1026: ! 1027: case IDD_MULTILIST: ! 1028: if(*pusPtr == EA_MVMT) /* m-m, do a recursive call to skip fld */ ! 1029: { ! 1030: pusPtr = (USHORT *) pMulti; /* points to field cnt */ ! 1031: pMulti = MultiTypeIndex(pMulti-sizeof(USHORT),*pusPtr); ! 1032: break; ! 1033: } ! 1034: /* Not yet implemented for Multi-valued single-type stuff... */ ! 1035: break; ! 1036: } ! 1037: } ! 1038: return(pMulti); ! 1039: } ! 1040: ! 1041: ! 1042: /* ! 1043: * Function name: EAValueString() ! 1044: * ! 1045: * Parameters: hwnd is the current window handle. ! 1046: * aEAVal is a pointer to an EA value field. ! 1047: * ! 1048: * Returns: a pointer to an ASCII description of the field value. ! 1049: * ! 1050: * Purpose: This routine takes a pointer to an EA Value (i.e. starting with ! 1051: * with $ffxx) and returns a pointer to a string representing the ! 1052: * value of the EA. This string must be Freed by the user when ! 1053: * finished with it. ! 1054: * ! 1055: * Usage/Warnings: NOTE: Not all GetMem's are totally error trapped. ! 1056: * The string returned is allocated in this procedure, ! 1057: * but it is the caller's responsibility to free the buffer. ! 1058: * ! 1059: * Calls: ! 1060: * ! 1061: */ ! 1062: ! 1063: CHAR *EAValueString(CHAR *aEAVal) ! 1064: { ! 1065: USHORT *pusPtr= (USHORT *) aEAVal; /* Points to EA Type */ ! 1066: CHAR *szRet,*szTemp; /* szRet points to return string */ ! 1067: ! 1068: switch(*pusPtr) ! 1069: { ! 1070: case EA_ASCIIZ: /* For asciiz strings, return MAXSHOWSIZE-1 chars */ ! 1071: case EA_ASCIIZFN: ! 1072: case EA_ASCIIZEA: ! 1073: case EA_ASN1: ! 1074: aEAVal += sizeof(USHORT); ! 1075: if(strlen(aEAVal)<MAXSHOWSIZE) ! 1076: { ! 1077: GetMem((PPVOID)&szRet, strlen(aEAVal)+1); ! 1078: strcpy(szRet,aEAVal); ! 1079: } ! 1080: else ! 1081: { ! 1082: GetMem((PPVOID)&szRet, MAXSHOWSIZE); ! 1083: strncpy(szRet,aEAVal,MAXSHOWSIZE-4); ! 1084: strcpy (szRet+MAXSHOWSIZE-4,"..."); ! 1085: szRet[MAXSHOWSIZE-1]=NULL; ! 1086: } ! 1087: return(szRet); ! 1088: ! 1089: case EA_LPASCII: /* Display up to first MAXSHOWSIZE-1 chars */ ! 1090: case EA_LPMETAFILE: ! 1091: pusPtr++; ! 1092: aEAVal += 2*sizeof(USHORT); ! 1093: if(*pusPtr < MAXSHOWSIZE) ! 1094: { ! 1095: GetMem((PPVOID)&szRet, *pusPtr +1); ! 1096: strncpy(szRet,aEAVal,*pusPtr); ! 1097: szRet[*pusPtr]=NULL; ! 1098: } ! 1099: else ! 1100: { ! 1101: GetMem((PPVOID)&szRet, MAXSHOWSIZE); ! 1102: strncpy(szRet,aEAVal,MAXSHOWSIZE-4); ! 1103: strcpy (szRet+MAXSHOWSIZE-4,"..."); ! 1104: szRet[MAXSHOWSIZE-1]=NULL; ! 1105: } ! 1106: return(szRet); ! 1107: ! 1108: /* For the rest of the types, just display the field type */ ! 1109: ! 1110: case EA_LPBINARY: ! 1111: szTemp = "*** LP Binary ***"; ! 1112: break; ! 1113: ! 1114: case EA_LPBITMAP: ! 1115: szTemp = "*** LP Bitmap ***"; ! 1116: break; ! 1117: ! 1118: case EA_LPICON: ! 1119: szTemp = "*** LP Icon ***"; ! 1120: break; ! 1121: ! 1122: case EA_MVMT: ! 1123: szTemp = "*** Multi-value Multi-type ***"; ! 1124: break; ! 1125: ! 1126: case EA_MVST: ! 1127: szTemp = "*** Multi-value Single-type ***"; ! 1128: break; ! 1129: ! 1130: default: ! 1131: szTemp = "*** Unknown EA type ***"; ! 1132: break; ! 1133: ! 1134: } ! 1135: GetMem((PPVOID)&szRet, strlen(szTemp)+1); /* Copy string from static to dynamic */ ! 1136: strcpy(szRet,szTemp); ! 1137: return(szRet); ! 1138: } ! 1139: ! 1140: ! 1141: /* ! 1142: * Function name: MultiAdd() ! 1143: * ! 1144: * Parameters: hwnd is the current window handle. ! 1145: * pFEA points to the current FEA. ! 1146: * pPDat gives the current m-m data. ! 1147: * ! 1148: * Returns: VOID. Modifies the current pFEA. ! 1149: * ! 1150: * Purpose: This routine is called by MultiTypeProc and handles the addition ! 1151: * of a subvalue to a multi-value, multi-type EA. ! 1152: * ! 1153: * Usage/Warnings: NOTE: Not all GetMem's are totally error trapped. ! 1154: * It is also possible that the add to the listbox could fail. ! 1155: * ! 1156: * Calls: AddEAProc() (thru PM), MultiTypeIndex() ! 1157: * ! 1158: */ ! 1159: ! 1160: VOID MultiAdd(HWND hwnd, HOLDFEA *pFEA,PASSDATA FAR *pPDat) ! 1161: { ! 1162: USHORT usSize; ! 1163: USHORT *pusPtr; ! 1164: CHAR aUtility[6]; /* Used to hold the header for all EA types */ ! 1165: CHAR *pInsert,*pValue; ! 1166: PASSDATA PDat; ! 1167: ! 1168: PDat.Point = pFEA->szName; ! 1169: ! 1170: if(!WinDlgBox(HWND_DESKTOP, /* Get the name and type */ ! 1171: hwnd, ! 1172: AddEAProc, ! 1173: NULL, ! 1174: IDD_ADDEA, ! 1175: &PDat)) ! 1176: return; /* They said cancel */ ! 1177: ! 1178: pusPtr = (USHORT *) aUtility; ! 1179: *pusPtr= ConvTable[usRetEAType].usPrefix; /* Set the type in header buf */ ! 1180: ! 1181: switch(ConvTable[usRetEAType].usFldType) ! 1182: { ! 1183: case IDD_ASCIIZ: /* make buffer look like: xx FF 00, size 3 */ ! 1184: usSize = 3; ! 1185: aUtility[2]=0; ! 1186: break; ! 1187: ! 1188: case IDD_LPDATA: /* make the buffer look like: xx FF 00 00, size 4 */ ! 1189: usSize = 4; ! 1190: pusPtr = (USHORT *) &aUtility[2]; ! 1191: *pusPtr= 0; ! 1192: break; ! 1193: ! 1194: case IDD_MULTILIST: ! 1195: usSize = 6; ! 1196: pusPtr = (USHORT *) &aUtility[2]; ! 1197: *pusPtr= 0; /* Zero out codepage */ ! 1198: pusPtr++; ! 1199: *pusPtr= 0; /* Zero out fld cnt */ ! 1200: break; ! 1201: } ! 1202: /* Increase EA size to accomodate the header */ ! 1203: ResizeMem(pFEA->aValue, pFEA->cbValue, pFEA->cbValue+usSize); ! 1204: ! 1205: pusPtr = (USHORT *) ((CHAR *) pFEA->aValue + pPDat->usMultiOffset); ! 1206: pusPtr+=2; /* Point to the current number of m-m fields */ ! 1207: ! 1208: /* Get ptr to beginning of current EA, scoot the rest down and insert ! 1209: the 3-4 byte header at the end of the list. */ ! 1210: pInsert = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset, *pusPtr); ! 1211: memmove(pInsert+usSize,pInsert, pFEA->cbValue-(pInsert-pFEA->aValue)); ! 1212: memcpy(pInsert,aUtility,usSize); ! 1213: ! 1214: pFEA->cbValue += usSize; /* Fix up the counts */ ! 1215: pPDat->cbMulti+= usSize; ! 1216: /* Set the PDat for call */ ! 1217: PDat.Point = (CHAR *) pFEA; ! 1218: PDat.cbMulti = pPDat->cbMulti; ! 1219: PDat.usMultiOffset = pPDat->usMultiOffset; ! 1220: PDat.usIndex = *pusPtr; ! 1221: ! 1222: if(!EditEAValue(hwnd,&PDat)) /* They canceled the edit */ ! 1223: { /* Move the EA's back to effectively kill the inserted header */ ! 1224: memmove(pInsert,pInsert+usSize,pFEA->cbValue-(pInsert-pFEA->aValue)); ! 1225: DosSetMem(pFEA->aValue, pFEA->cbValue-usSize, fPERM|PAG_COMMIT); ! 1226: pFEA->cbValue -= usSize; /* Adjust counters */ ! 1227: pPDat->cbMulti-= usSize; ! 1228: ! 1229: return; ! 1230: } ! 1231: ! 1232: /* Reset pusPtr since EditEAValue could have moved the base address */ ! 1233: pusPtr = (USHORT *) ((CHAR *) pFEA->aValue + pPDat->usMultiOffset); ! 1234: pusPtr+=2; ! 1235: ! 1236: pInsert = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset, *pusPtr); ! 1237: ! 1238: *pusPtr += 1; /* Field cnt incremented AFTER call to Edit */ ! 1239: ! 1240: pValue = EAValueString(pInsert); /* Add new field to the list box */ ! 1241: ! 1242: WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM, ! 1243: MPFROM2SHORT(LIT_END,0), ! 1244: MPFROMP(pValue)); ! 1245: FreeMem(pValue); ! 1246: ! 1247: FILE_CHANGED = TRUE; ! 1248: } ! 1249:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.