|
|
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.