void TestRemove( void ) { UInt16* item1; UInt16* item2; ASSERT( ListIsEmpty( list )); AddTwoItems(); item1 = ListFirst( list ); ListTakeOut( list, item1 ); ASSERT( ListSize( list ) == 1 ); MemPtrFree( item1 ); item1 = ListFirst( list ); item2 = ListLast( list ); ASSERT_UINT16_EQUAL_MSG( "First item: ", 10, *item1 ); ASSERT_UINT16_EQUAL_MSG( "Last item: ", 10, *item2 ); ListTakeOut( list, item2 ); ASSERT( ListSize( list ) == 0 ); ASSERT( ListFirst( list ) == NULL ); ASSERT( ListLast( list ) == NULL ); MemPtrFree( item2 ); }
// return ptr void *ListTrim(LIST *list) { void *item; //list->curr = list->head->prev; ListLast(list); item = ListRemove(list); ListLast(list); return item; }
VOID FAR CleanupImportedTypeLibs() { LPIMPORTLIB lpImpLib; LPENTRY pEntry; // free up each of the referenced lptinfo's if (typlib.pEntry) { pEntry = (LPENTRY)ListFirst(typlib.pEntry); // point to first entry for (;;) { // release the ITypeInfo if (pEntry->type.lptinfo != NULL && (pEntry->type.tentrykind & tFORWARD) == 0) pEntry->type.lptinfo->Release(); // advance to next entry if not all done if (pEntry == ListLast(typlib.pEntry)) break; // exit if all done pEntry = (LPENTRY)pEntry->type.pNext; } } if (typlib.pImpLib) { // only if any imported type libraries // point to first imported library entry lpImpLib = (LPIMPORTLIB)ListFirst(typlib.pImpLib); for (;;) { if (lpImpLib->lptcomp) { lpImpLib->lptcomp->Release(); } if (lpImpLib->lptlibattr) { Assert (lpImpLib->lptlib); lpImpLib->lptlib->ReleaseTLibAttr(lpImpLib->lptlibattr); } if (lpImpLib->lptlib) { lpImpLib->lptlib->Release(); } // advance to next entry if not all done if (lpImpLib == (LPIMPORTLIB)ListLast(typlib.pImpLib)) break; // exit if all done lpImpLib = lpImpLib->pNext; } // WHILE } }
// return void void ListConcat(LIST *list1, LIST *list2) { void *item; // add to list1 //list1->curr = list1->head->prev; //list2->curr = list2->head->next; ListLast(list1); ListFirst(list2); while (list2->curr != list2->head) { item = ListRemove(list2); ListAdd(list1, item); } // rmv list2 free_list(list2); }
VOID NEAR OutputBaseInterfaces ( ICreateTypeInfo FAR* lpdtinfo, LPENTRY pEntry, TYPEKIND tkind ) { HREFTYPE hreftype; HRESULT res; LPINTER lpinterList = pEntry->type.inter.interList; LPINTER lpinter; SHORT i; INT implTypeFlags; Assert (lpinterList); // caller should have checked this for use // point to first base interface lpinter = (LPINTER)ListFirst(lpinterList); for (i=0;;i++) { // get index of typeinfo of base interface/dispinterface if (lpinter->ptypeInter->lptinfo == NULL) ItemError(szFmtErrOutput, lpinter->ptypeInter->szName, OERR_NO_DEF); CHECKRESULT(lpdtinfo->AddRefTypeInfo(lpinter->ptypeInter->lptinfo, &hreftype)); CHECKRESULT(lpdtinfo->AddImplType(i, hreftype)); // if (tkind == TKIND_COCLASS) { // need to always set the flags for items in a coclass implTypeFlags = 0; if (lpinter->fAttr & fDEFAULT) implTypeFlags |= IMPLTYPEFLAG_FDEFAULT; if (lpinter->fAttr & fRESTRICTED) implTypeFlags |= IMPLTYPEFLAG_FRESTRICTED; if (lpinter->fAttr & fSOURCE) implTypeFlags |= IMPLTYPEFLAG_FSOURCE; CHECKRESULT(lpdtinfo->SetImplTypeFlags(i, implTypeFlags)); } // advance to next entry if not all done if (lpinter == (LPINTER)ListLast(lpinterList)) break; // exit if all done lpinter = (LPINTER)lpinter->pNext; } // WHILE }
void TestTraverse( void ) { UInt16* item1; UInt16* item2; ASSERT( ListIsEmpty( list )); AddTwoItems(); item1 = ListFirst( list ); item2 = ListNext( list, item1 ); ASSERT_UINT16_EQUAL_MSG( "First item: ", 6, *item1 ); ASSERT_UINT16_EQUAL_MSG( "Next item: ", 10, *item2 ); item1 = ListLast( list ); ASSERT_UINT16_EQUAL_MSG( "Last item: ", 10, *item1 ); item2 = ListNext( list, item1 ); ASSERT_MSG( "Item after last in list: ", item2 == NULL ); }
// return 0 (success) or -1 (fail) int ListAppend(LIST *list, void *item) { //list->curr = list->head->prev; ListLast(list); return ListAdd(list, item); }
VOID NEAR OutputElems ( ICreateTypeInfo FAR* lpdtinfo, LPELEM pElemList, TYPEKIND tkind ) { LPELEM pElem; HRESULT res; UINT iElem = 0; // element index VARDESC VarDesc; if (pElemList == NULL) return; pElem = (LPELEM)ListFirst(pElemList); // point to first entry for (;;) { // First fill in the VARDESC structure with the element's info SETITEMCUR(pElem->szElemName); VarDesc.memid = DISPID_UNKNOWN; // assume not a dispinterface // Set up varkind switch (tkind) { case TKIND_ENUM: // for enum elements case TKIND_MODULE: // for const's VarDesc.varkind = VAR_CONST; VarDesc.lpvarValue = pElem->lpElemVal; // * to value if (tkind == TKIND_MODULE) goto DoLoadElemDesc; // set up the tdesc // For ENUM elements, can't call LoadElemDesc, because // we have no pElem->elemType. Do the required work here. VarDesc.elemdescVar.tdesc.vt = VT_INT; // element type // is an INT VarDesc.elemdescVar.idldesc.wIDLFlags = 0; // no IDL info #ifdef WIN16 VarDesc.elemdescVar.idldesc.bstrIDLInfo = NULL; #else //WIN16 VarDesc.elemdescVar.idldesc.dwReserved = 0; #endif //WIN16 break; case TKIND_RECORD: case TKIND_UNION: VarDesc.varkind = VAR_PERINSTANCE; goto DoLoadElemDesc; default: #if FV_PROPSET Assert(tkind == TKIND_DISPATCH || tkind == TKIND_PROPSET); #else //FV_PROPSET Assert(tkind == TKIND_DISPATCH); #endif //FV_PROPSET VarDesc.varkind = VAR_DISPATCH; // id' attribute required Assert (pElem->attr.fAttr & fID); VarDesc.memid = pElem->attr.lId; DoLoadElemDesc: // Set up elemdescVar. Contains name, and type of item. LoadElemDesc(lpdtinfo, &(VarDesc.elemdescVar), pElem); } // VarDesc.oInst is not used when doing AddVarDesc VarDesc.wVarFlags = 0; if (pElem->attr.fAttr & fREADONLY) VarDesc.wVarFlags |= (WORD)VARFLAG_FREADONLY; if (pElem->attr.fAttr & fSOURCE) VarDesc.wVarFlags |= (WORD)VARFLAG_FSOURCE; if (pElem->attr.fAttr & fBINDABLE) VarDesc.wVarFlags |= (WORD)VARFLAG_FBINDABLE; if (pElem->attr.fAttr & fREQUESTEDIT) VarDesc.wVarFlags |= (WORD)VARFLAG_FREQUESTEDIT; if (pElem->attr.fAttr & fDISPLAYBIND) VarDesc.wVarFlags |= (WORD)VARFLAG_FDISPLAYBIND; if (pElem->attr.fAttr & fDEFAULTBIND) VarDesc.wVarFlags |= (WORD)VARFLAG_FDEFAULTBIND; if (pElem->attr.fAttr & fHIDDEN) VarDesc.wVarFlags |= (WORD)VARFLAG_FHIDDEN; // Now define the element CHECKRESULT(lpdtinfo->AddVarDesc(iElem, &VarDesc)); // Lastly, set element's remaining attributes: CHECKRESULT(lpdtinfo->SetVarName(iElem, ToW(pElem->szElemName))); if (pElem->attr.fAttr & fHELPSTRING) CHECKRESULT(lpdtinfo->SetVarDocString(iElem, ToW(pElem->attr.lpszHelpString))); if (pElem->attr.fAttr & fHELPCONTEXT) CHECKRESULT(lpdtinfo->SetVarHelpContext(iElem, pElem->attr.lHelpContext)); // advance to next entry if not all done if (pElem == (LPELEM)ListLast(pElemList)) break; // exit if all done pElem = pElem->pNext; iElem++; // advance element counter } }
VOID NEAR OutputFuncs ( ICreateTypeInfo FAR* lpdtinfo, LPENTRY pEntry, LPFUNC pFuncList, TYPEKIND tkind ) { LPFUNC pFunc; LPELEM pArg; HRESULT res; UINT iFunc = 0; // function index LPOLESTR lpszDllName; LPSTR lpszProcName; SHORT i; FUNCDESC FuncDesc; LPOLESTR FAR* lplpszArgName; if (pFuncList == NULL) // just return if no functions to output return; FuncDesc.lprgelemdescParam = rgFuncArgs; // set up array of args pFunc = (LPFUNC)ListFirst(pFuncList); // point to first entry #if FV_UNICODE_OLE lpszDllName = (pEntry->attr.fAttr & fDLLNAME ? ToNewW(pEntry->attr.lpszDllName) : NULL); #else lpszDllName = pEntry->attr.lpszDllName; #endif for (;;) { // Fill in the FUNCDESC structure with the function's info // set up funckind switch (tkind) { case TKIND_MODULE: FuncDesc.funckind = FUNC_STATIC; break; case TKIND_INTERFACE: FuncDesc.funckind = FUNC_PUREVIRTUAL; break; case TKIND_DISPATCH: FuncDesc.funckind = FUNC_DISPATCH; break; default: Assert(FALSE); } // set up invkind FuncDesc.invkind = INVOKE_FUNC; // default if (pFunc->func.attr.fAttr & fPROPGET) FuncDesc.invkind = INVOKE_PROPERTYGET; else if (pFunc->func.attr.fAttr & fPROPPUT) FuncDesc.invkind = INVOKE_PROPERTYPUT; else if (pFunc->func.attr.fAttr & fPROPPUTREF) FuncDesc.invkind = INVOKE_PROPERTYPUTREF; // set up callconv if (pFunc->func.attr.fAttr2 & f2PASCAL) // CC_MACPASCAL if /mac specified, CC_MSCPASCAL otherwise FuncDesc.callconv = (CALLCONV)(SysKind == SYS_MAC ? CC_MACPASCAL: CC_MSCPASCAL); else if (pFunc->func.attr.fAttr2 & f2CDECL) FuncDesc.callconv = CC_CDECL; else if (pFunc->func.attr.fAttr2 & f2STDCALL) FuncDesc.callconv = CC_STDCALL; #ifdef DEBUG else Assert(FALSE); #endif //DEBUG FuncDesc.wFuncFlags = 0; if (pFunc->func.attr.fAttr & fRESTRICTED) FuncDesc.wFuncFlags |= (WORD)FUNCFLAG_FRESTRICTED; if (pFunc->func.attr.fAttr & fSOURCE) FuncDesc.wFuncFlags |= (WORD)FUNCFLAG_FSOURCE; if (pFunc->func.attr.fAttr & fBINDABLE) FuncDesc.wFuncFlags |= (WORD)FUNCFLAG_FBINDABLE; if (pFunc->func.attr.fAttr & fREQUESTEDIT) FuncDesc.wFuncFlags |= (WORD)FUNCFLAG_FREQUESTEDIT; if (pFunc->func.attr.fAttr & fDISPLAYBIND) FuncDesc.wFuncFlags |= (WORD)FUNCFLAG_FDISPLAYBIND; if (pFunc->func.attr.fAttr & fDEFAULTBIND) FuncDesc.wFuncFlags |= (WORD)FUNCFLAG_FDEFAULTBIND; if (pFunc->func.attr.fAttr & fHIDDEN) FuncDesc.wFuncFlags |= (WORD)FUNCFLAG_FHIDDEN; // set up cParams & cParamsOpt FuncDesc.cParams = pFunc->cArgs; FuncDesc.cParamsOpt = pFunc->cOptArgs; //NOTE: cParamsOpt can be set to -1, to note that last parm is a //NOTE: [safe] array of variant args. This corresponds to the //NOTE: 'vararg' attribute in the input description. If this was //NOTE: specified, the parser set pFunc->cOptArgs to -1 for us. // set up misc unused stuff FuncDesc.oVft = 0; // only used for FUNC_VIRTUAL FuncDesc.cScodes = -1; // list of SCODEs unknown FuncDesc.lprgscode = NULL; // set id field if 'id' attribute specified if (pFunc->func.attr.fAttr & fID) FuncDesc.memid = pFunc->func.attr.lId; else FuncDesc.memid = DISPID_UNKNOWN; // set up elemdescFunc // Contains the ID, name, and return type of the function LoadElemDesc(lpdtinfo, &(FuncDesc.elemdescFunc), &pFunc->func); // save function name lplpszArgName = rgszFuncArgNames; *lplpszArgName++ = ToNewW(pFunc->func.szElemName); SETITEMCUR(pFunc->func.szElemName); // set up the lprgelemdescParam array of info for each parameter pArg = pFunc->argList; // point to last arg, if any for (i = 0; i < pFunc->cArgs; i++) { pArg = pArg->pNext; // point to next arg (first arg // first time through loop) LoadElemDesc(lpdtinfo, &(FuncDesc.lprgelemdescParam[i]), pArg); *lplpszArgName++ = ToNewW(pArg->szElemName); // save arg name } // Define the function item: CHECKRESULT(lpdtinfo->AddFuncDesc(iFunc, &FuncDesc)); // set the names of the function and the parameters Assert(i == pFunc->cArgs); // don't set the name of the last param for proput/putref functions if (pFunc->func.attr.fAttr & (fPROPPUT | fPROPPUTREF)) { i--; } CHECKRESULT(lpdtinfo->SetFuncAndParamNames(iFunc, rgszFuncArgNames, i+1)); #if FV_UNICODE_OLE // free the unicode function & param names lplpszArgName = rgszFuncArgNames; for (i = 0; i <= pFunc->cArgs; i++) { _ffree(*lplpszArgName); // done with unicode name lplpszArgName++; } #endif //FV_UNICODE_OLE // Set the function item's remaining attributes: if (pFunc->func.attr.fAttr & fHELPSTRING) CHECKRESULT(lpdtinfo->SetFuncDocString(iFunc, ToW(pFunc->func.attr.lpszHelpString))); if (pFunc->func.attr.fAttr & fHELPCONTEXT) CHECKRESULT(lpdtinfo->SetFuncHelpContext(iFunc, pFunc->func.attr.lHelpContext)); // Handle case of a DLL entrypoint if (pFunc->func.attr.fAttr & fENTRY) { // If high word of name is zero, then call by ordnal // If high word of name is non-zero, then call by name // (same as GetProcAddress) lpszProcName = pFunc->func.attr.lpszProcName; #if FV_UNICODE_OLE if (HIWORD(lpszProcName)) { lpszProcName = (LPSTR)ToW(lpszProcName); } #endif //FV_UNICODE_OLE CHECKRESULT(lpdtinfo->DefineFuncAsDllEntry(iFunc, lpszDllName, (LPOLESTR)lpszProcName)); } // advance to next entry if not all done if (pFunc == (LPFUNC)ListLast(pFuncList)) break; // exit if all done pFunc = (LPFUNC)pFunc->func.pNext; iFunc++; // advance function counter } #if FV_UNICODE_OLE if (lpszDllName) _ffree(lpszDllName); // done with unicode name #endif //FV_UNICODE_OLE }
// For each library entry, creates a typeinfo in the typelib, // and fills it in. VOID NEAR OutputTypeInfos ( ICreateTypeLib FAR * lpdtlib ) { LPENTRY pEntry; TYPEKIND tkind; HRESULT res; ICreateTypeInfo FAR* lpdtinfo; WORD wTypeFlags; // First allocate an array of ELEMDESCs to hold the max # of // args of any function we need to describe. rgFuncArgs = (ELEMDESC FAR*)_fmalloc(cArgsMax * sizeof(ELEMDESC)); rgszFuncArgNames = (LPOLESTR FAR *)_fmalloc((cArgsMax+1) * sizeof(LPOLESTR)); if (rgFuncArgs == NULL || rgszFuncArgNames == NULL) ParseError(ERR_OM); // pass 1 -- create the typeinfo's pEntry = (LPENTRY)ListFirst(typlib.pEntry); // point to first entry for (;;) { // determine if we are going to create a typeinfo for this guy switch (pEntry->type.tentrykind) { case tTYPEDEF: if (pEntry->attr.fAttr) // create lpdtinfo only if break; // this is a 'PUBLIC' typedef NoTypeInfos: pEntry->lpdtinfo = NULL; // no lpdtinfo for this case tREF: // no typeinfo's made for these case tINTRINSIC: goto Next_Entry1; default: // no typeinfo's made for forward declarations if (pEntry->type.tentrykind & tFORWARD) goto NoTypeInfos; if (pEntry->type.tentrykind & tIMPORTED) goto Next_Entry1; // nothing for imported types break; } // 1. determine kind of typeinfo to create tkind = rgtkind[pEntry->type.tentrykind]; // 2. Create type library entry (TypeInfo) of a given name/and // type, getting a pointer to the ICreateTypeInfo interface SETITEMCUR(pEntry->type.szName); CHECKRESULT(lpdtlib->CreateTypeInfo(ToW(pEntry->type.szName), tkind, &lpdtinfo)); pEntry->lpdtinfo = lpdtinfo; // 3. Set the item's attributes: if (pEntry->attr.fAttr & fUUID) CHECKRESULT(lpdtinfo->SetGuid(*pEntry->attr.lpUuid)); if (pEntry->attr.fAttr & fHELPSTRING) CHECKRESULT(lpdtinfo->SetDocString(ToW(pEntry->attr.lpszHelpString))); if (pEntry->attr.fAttr & fHELPCONTEXT) CHECKRESULT(lpdtinfo->SetHelpContext(pEntry->attr.lHelpContext)); if (pEntry->attr.fAttr & fVERSION) CHECKRESULT(lpdtinfo->SetVersion(pEntry->attr.wVerMajor, pEntry->attr.wVerMinor)); // 4. save lptinfo for this guy in case somebody references it CHECKRESULT(lpdtinfo->QueryInterface(IID_ITypeInfo, (VOID FAR* FAR*)&pEntry->type.lptinfo)); // if this type has a forward declaration if (pEntry->lpEntryForward) { // copy "real" type info over top of forward declaration, // because folks have pointers to the forward declaration pEntry->lpEntryForward->type.tdesc = pEntry->type.tdesc; pEntry->lpEntryForward->type.lptinfo = pEntry->type.lptinfo; // Only need to copy these 2 fields from the type (the // others aren't referenced at type creation time. } Next_Entry1: // advance to next entry if not all done if (pEntry == (LPENTRY)ListLast(typlib.pEntry)) break; // exit if all done pEntry = (LPENTRY)pEntry->type.pNext; } // pass 2 -- process each entry pEntry = (LPENTRY)ListFirst(typlib.pEntry); // point to first entry for (;;) { // 1. Get our lpdtinfo again if we have one switch (pEntry->type.tentrykind) { case tREF: case tINTRINSIC: goto Next_Entry2; // these guys don't have lpdtinfo field default: if (pEntry->type.tentrykind & tIMPORTED) goto Next_Entry2; // no lpdtinfo field break; } lpdtinfo = pEntry->lpdtinfo; if (lpdtinfo == NULL) // skip if no lpdtinfo created goto Next_Entry2; // (forward decl or non-public typedef) // set up for error reporting SETITEMCUR(pEntry->type.szName); // 2. determine kind of typeinfo we're dealing with tkind = rgtkind[pEntry->type.tentrykind]; // 2a. Set the typeinfo flags wTypeFlags = 0; if (tkind == TKIND_COCLASS) { // COCLASSs always have FCANCREATE bit set wTypeFlags |= TYPEFLAG_FCANCREATE; // these are only valid on COCLASSs if (pEntry->attr.fAttr & fAPPOBJECT) wTypeFlags |= (WORD)TYPEFLAG_FAPPOBJECT; if (pEntry->attr.fAttr & fLICENSED) wTypeFlags |= (WORD)TYPEFLAG_FLICENSED; if (pEntry->attr.fAttr & fPREDECLID) wTypeFlags |= (WORD)TYPEFLAG_FPREDECLID; } if (pEntry->attr.fAttr & fHIDDEN) wTypeFlags |= (WORD)TYPEFLAG_FHIDDEN; if (pEntry->attr.fAttr2 & f2CONTROL) wTypeFlags |= (WORD)TYPEFLAG_FCONTROL; if (pEntry->attr.fAttr2 & f2NONEXTENSIBLE) wTypeFlags |= (WORD)TYPEFLAG_FNONEXTENSIBLE; if (pEntry->attr.fAttr2 & f2DUAL) // DUAL implies OLEAUTOMATION wTypeFlags |= (WORD)(TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION); if (pEntry->attr.fAttr2 & f2OLEAUTOMATION) wTypeFlags |= (WORD)TYPEFLAG_FOLEAUTOMATION; CHECKRESULT(lpdtinfo->SetTypeFlags(wTypeFlags)); // 3. now process each kind of entry switch (tkind) { case TKIND_ALIAS: OutputAlias(lpdtinfo, pEntry->type.td.ptypeAlias); break; case TKIND_RECORD: // struct's, enum's, and union's are case TKIND_ENUM: // all very similar case TKIND_UNION: OutputElems(lpdtinfo, pEntry->type.structenum.elemList, tkind); break; case TKIND_MODULE: OutputFuncs(lpdtinfo, pEntry, pEntry->module.funcList, tkind); OutputElems(lpdtinfo, pEntry->module.constList, tkind); break; case TKIND_INTERFACE: OutputInterface(lpdtinfo, pEntry); break; case TKIND_DISPATCH: OutputDispinter(lpdtinfo, pEntry); break; case TKIND_COCLASS: OutputClass(lpdtinfo, pEntry); break; #if FV_PROPSET case TKIND_PROPSET: // CONSIDER: (FV_PROPSET) do something with base_propset name OutputElems(lpdtinfo, pEntry->propset.propList, tkind); break; #endif //FV_PROPSET default: Assert(FALSE); }; // 3a. Set the alignment for this TypeInfo. Must be done before // Layout(). CHECKRESULT(lpdtinfo->SetAlignment(iAlignMax)); // 4. Compile this typeinfo we've just created. SETITEMCUR(pEntry->type.szName); CHECKRESULT(lpdtinfo->LayOut()); // 5. Cleanup. All done with lpdtinfo. lpdtinfo->Release(); Next_Entry2: // advance to next entry if not all done if (pEntry == (LPENTRY)ListLast(typlib.pEntry)) break; // exit if all done pEntry = (LPENTRY)pEntry->type.pNext; } // now clean up everything else _ffree(rgFuncArgs); // done with function args we allocated _ffree(rgszFuncArgNames); }
// find type defined in an external type library, // and add it to the type table if found. // lpszLibName is NULL if we're to look in ALL external type libraries. LPTYPE FAR FindExtType ( LPSTR lpszLibName, LPSTR lpszTypeName ) { LPIMPORTLIB lpImpLib; HRESULT res; ULONG lHashVal; ITypeInfo FAR* lptinfo; ITypeComp FAR* lptcomp; Assert (lpszTypeName != NULL); if (typlib.pImpLib != NULL) // if any imported type libraries { // point to first imported library entry lpImpLib = (LPIMPORTLIB)ListFirst(typlib.pImpLib); for (;;) { // if we're to look in all libraries, or this specific lib if (lpszLibName == NULL || !FCmpCaseIns(lpszLibName, lpImpLib->lpszLibName)) { SETITEMCUR(lpImpLib->lpszFileName); lHashVal = LHashValOfNameSysA(lpImpLib->lptlibattr->syskind, lpImpLib->lptlibattr->lcid, lpszTypeName); CHECKRESULT(lpImpLib->lptcomp->BindType(ToW(lpszTypeName), lHashVal, &lptinfo, &lptcomp)); if (lptinfo) // if found { // create a type table entry for this guy ListInsert(&typlib.pEntry, sizeof(TYPE)); // lpszTypeName will get freed by caller. // We must allocate new memory for it. typlib.pEntry->type.szName = _fstrdup(lpszTypeName); // CONSIDER: do a GetTypeAttr on this guy, // to ensure it's not a 'module' type typlib.pEntry->type.tdesc.vt = VT_USERDEFINED; // init this now in case of error, since // error cleanup code looks at this. typlib.pEntry->type.lptinfo = NULL; LPTYPEATTR ptypeattr; TENTRYKIND tentrykind; CHECKRESULT(lptinfo->GetTypeAttr(&ptypeattr)); // Get the interface typeinfo instead of // the Dispinteface version. if (ptypeattr->wTypeFlags & TYPEFLAG_FDUAL){ ITypeInfo FAR* lptinfo2; HREFTYPE hreftype; CHECKRESULT(lptinfo->GetRefTypeOfImplType((unsigned int)-1, &hreftype)); CHECKRESULT(lptinfo->GetRefTypeInfo(hreftype, &lptinfo2)); lptinfo->Release(); lptinfo->ReleaseTypeAttr(ptypeattr); lptinfo = lptinfo2; CHECKRESULT(lptinfo->GetTypeAttr(&ptypeattr)); } typlib.pEntry->type.lptinfo = lptinfo; // assume generic imported type tentrykind = (TENTRYKIND)(rgtentrykind[ptypeattr->typekind] | tIMPORTED); if (lpszLibName) { tentrykind = (TENTRYKIND)(tentrykind | tQUAL); } typlib.pEntry->type.tentrykind = tentrykind; typlib.pEntry->type.import.wTypeFlags = ptypeattr->wTypeFlags; lptinfo->ReleaseTypeAttr(ptypeattr); return &(typlib.pEntry->type); // all done } } // advance to next entry if not all done if (lpImpLib == (LPIMPORTLIB)ListLast(typlib.pImpLib)) break; // exit if all done lpImpLib = lpImpLib->pNext; } // WHILE } return (LPTYPE)NULL; //type not found }
VOID NEAR HOutElems ( LPELEM pElemList, CHAR * szPrefix, CHAR * szSep, CHAR * szSepLast, BOOL fEnum ) { LPELEM pElem; WORD cDims; ARRAYDESC FAR* lpAD; BOOL fHex; LPOLESTR lpch; CHAR * pch; CHAR buf[2]; UINT cch; pElem = (LPELEM)ListFirst(pElemList); // point to first entry #pragma warning(disable:4127) while (TRUE) #pragma warning(default:4127) { HOut(szPrefix); if (!fEnum) { // output elem type, with the right number of "*'s" HOutType(pElem->elemType); HOut(" "); } XOutF(pElem->szElemName); #ifdef PROFILE cVarsTotal++; #endif //PROFILE if (!fEnum && pElem->elemType->tdesc.vt == VT_CARRAY) { // base type already outputted before name above lpAD = pElem->elemType->tdesc.lpadesc; for (cDims = 0; cDims < lpAD->cDims; cDims++) { HOut("["); #if 0 // arrays of the form "a[]" aren't supported if (lpAD->rgbounds[cDims].cElements) #endif //0 HOutLongNum((long)lpAD->rgbounds[cDims].cElements, FALSE); HOut("]"); } } if (pElem->attr.fAttr2 & f2GotConstVal) { HOut(" = "); fHex = FALSE; if (!fEnum) { // display all the unsigned constants in Hex form switch (pElem->elemType->tdesc.vt) { case VT_UI1: case VT_UI2: case VT_UI4: case VT_UINT: case VT_ERROR: fHex = TRUE; break; default: break; } } // output the constant element's value switch (pElem->lpElemVal->vt) { case VT_I2: case VT_BOOL: HOutShortNum(pElem->lpElemVal->iVal, fHex); break; case VT_I4: case VT_ERROR: HOutLongNum(pElem->lpElemVal->lVal, fHex); break; case VT_BSTR: HOut("\""); // output 1 char at a time, in order to handle // escape sequences in strings lpch = pElem->lpElemVal->bstrVal; cch = SysStringLen(lpch); while (cch) { switch(*lpch) { case 0x0: pch = "\\0"; break; case 0x7: pch = "\\a"; break; case 0x8: pch = "\\b"; break; case 0x9: pch = "\\t"; break; case 0xA: if (SysKind == SYS_MAC) pch = "\\r"; else pch = "\\n"; break; case 0xB: pch = "\\v"; break; case 0xC: pch = "\\f"; break; case 0xD: if (SysKind == SYS_MAC) pch = "\\n"; else pch = "\\r"; break; default: #ifdef WIN32 SideAssert (WideCharToMultiByte(CP_ACP, 0, lpch, 1, buf, 1, NULL, NULL) != 0); #else //WIN32 buf[0] = *lpch; #endif //WIN32 buf[1] = '\0'; pch = buf; break; } HOut(pch); // output the char lpch++; cch--; } HOut("\""); break; // CONSIDER: support more constant types. default: Assert(FALSE); } } // advance to next entry if not all done if (pElem == (LPELEM)ListLast(pElemList)) { XOut(szSepLast); break; // exit if all done } XOut(szSep); pElem = pElem->pNext; } }
VOID NEAR HOutFuncs ( LPFUNC pFuncList, TENTRYKIND tentryKind ) { LPFUNC pFunc; if (pFuncList == NULL) // nothing to output if no functions return; pFunc = (LPFUNC)ListFirst(pFuncList); // point to first entry #pragma warning(disable:4127) while (TRUE) #pragma warning(default:4127) { #ifndef PROFILE if (tentryKind == tINTERFACE) { if (fSpecifiedInterCC) { // set up STDMETHODCALLTYPE based on the calling // convention and SYSKIND if (pFunc->func.attr.fAttr2 & f2CCDEFAULTED) SetCallType(CALL_DEFAULT); else if (pFunc->func.attr.fAttr2 & f2PASCAL) SetCallType(CALL_PASCAL); else if (pFunc->func.attr.fAttr2 & f2STDCALL) SetCallType(CALL_STDCALL); else { Assert(pFunc->func.attr.fAttr2 & f2CDECL) SetCallType(CALL_CDECL); } } HOut(szHeadOleFuncPrefix1); // leading spaces HOut(szHeadOleFuncPrefix2); if (pFunc->func.elemType->tdesc.vt == VT_HRESULT) HOut("("); else { HOut("_("); // output function return type HOutType(pFunc->func.elemType); HOut(szHeadOleFuncPrefix3); } HOutPropPrefix(pFunc); XOutF(pFunc->func.szElemName); HOut(szHeadOleArgPrefix1); if (pFunc->cArgs) { HOut(szHeadOleArgPrefix2); // output list of variables, separating them by // commas, with nothing after last item HOutElems(pFunc->argList, "", ", ", "", FALSE); } XOut(szHeadOleArgSuffix); } else #endif //!PROFILE { HOut(szHeadOleFuncPrefix1); // leading spaces if (tentryKind == tMODULE) HOut ("extern "); // output function return type HOutType(pFunc->func.elemType); HOut(" "); // output calling convention if (!(pFunc->func.attr.fAttr2 & f2CCDEFAULTED)) { if (pFunc->func.attr.fAttr2 & f2PASCAL) HOut("__pascal "); else if (pFunc->func.attr.fAttr2 & f2CDECL) HOut("__cdecl "); else if (pFunc->func.attr.fAttr2 & f2STDCALL) HOut("__stdcall "); #ifdef DEBUG else Assert(FALSE); #endif //DEBUG } HOutPropPrefix(pFunc); XOutF(pFunc->func.szElemName); Assert(pFunc->func.elemType->tdesc.vt != VT_CARRAY); XOut("("); #ifdef PROFILE cArgsTotal += pFunc->cArgs; cFuncsTotal++; #endif //PROFILE if (pFunc->cArgs == 0) { HOut("void"); } else { // output list of variables, separating them by // commas, with nothing after last item HOutElems(pFunc->argList, "", ", ", "", FALSE); #ifdef PROFILE cVarsTotal-= pFunc->cArgs; // would be counted twice #endif //PROFILE } XOut(");\n"); } // advance to next entry if not all done if (pFunc == (LPFUNC)ListLast(pFuncList)) break; // exit if all done pFunc = (LPFUNC)pFunc->func.pNext; } if (fSpecifiedInterCC) { SetCallType(CALL_DEFAULT); // reset to default STDMETHODCALLTYPE } }
VOID NEAR HOutInterface ( LPENTRY pEntry ) { LPSTR lpszBaseName; TENTRYKIND tentrykind; LPINTER lpInterFirst; // first base interface, if any LPINTER lpInterLast; // second/last base interface, if any tentrykind = pEntry->type.tentrykind; if (tentrykind & tFORWARD) { // UNDONE: proper OLE format for forward declaration of interface? // UNDONE: I don't think this will work in C. I think it wants: // UNDONE: typedef interface <interfacename> <interfacename>; HOut("\ninterface "); HOutF(pEntry->type.szName); HOut(";\n"); return; } HOutGuid(&pEntry->attr, ((tentrykind == tDISPINTER) ? szHeadGuidDIID: szHeadGuidIID), pEntry->type.szName); lpszBaseName = NULL; lpInterFirst = NULL; if (pEntry->type.inter.interList) { lpInterFirst = (LPINTER)ListFirst(pEntry->type.inter.interList); lpInterLast = (LPINTER)ListLast(pEntry->type.inter.interList); // We assume there's only single inheritance at this point // But in the case of a dispinterface, we could have the first // base interface be IDispatch, and the 2nd base interface be // the interface that we're capable of dispatching on. In any // case, there can't be more than 2 interfaces in the list. Assert((LPINTER)lpInterFirst->pNext == lpInterLast); lpszBaseName = lpInterFirst->ptypeInter->szName; Assert(lpszBaseName); } // first output the header comment HOut((tentrykind == tDISPINTER) ? szHeadDispinter: szHeadInter); HOutF(pEntry->type.szName); HOut(szHeadOleSuffix3); // then output the OLE header HOut(szHeadOlePrefix0); HOutF(pEntry->type.szName); HOut("\n\n"); HOut(szHeadOlePrefix1); if (lpszBaseName) HOut("_"); HOut("("); HOutF(pEntry->type.szName); if (lpszBaseName) // if this inherits from somebody { // then add ", <baseinterface>" HOut(", "); HOutF(lpszBaseName); } HOut(szHeadOlePrefix2); if (tentrykind == tDISPINTER) { Assert (lpszBaseName); HOut(szHeadOlePrefix7); HOut(szHeadIUnknown); HOut(szHeadIDispatch); HOut(szHeadOleSuffix7); if (lpInterFirst != lpInterLast) { // specifies an interface that is dispatchable HOut(szHeadDispatchable); HOutF(lpInterLast->ptypeInter->szName); HOut(szHeadOleSuffix3); } // first output the properties (commented out) in "struct" format if (pEntry->dispinter.propList) { XOut(szHeadOlePrefix3); XOutF(pEntry->type.szName); XOut(szHeadOlePrefix5); HOutElems(pEntry->dispinter.propList, " ", ";\n", ";\n", FALSE); HOut(szHeadOleSuffix1); } // then output the methods (commented out) in "normal" format if (pEntry->dispinter.methList) { XOut(szHeadOlePrefix3); XOutF(pEntry->type.szName); XOut(szHeadOlePrefix6); HOutFuncs(pEntry->dispinter.methList, tDISPINTER); HOut(szHeadOleSuffix1); } } else { // an interface // output interface functions, and base interface functions (if any) HOutBaseInter(pEntry, FALSE); } // lastly, output the close curly HOut(szHeadOleSuffix2); }
VOID FAR OutputHFile ( CHAR * szHFile ) { LPENTRY pEntry; #ifdef WIN16 // convert szHFile in-place to OEM char set AnsiToOem(szHFile, szHFile); // don't bother converting back since this string is not used again #endif // WIN16 // open the file hHFile = fopen(szHFile, "w"); // open output file if (hHFile == NULL) ParseError(ERR_CANT_OPEN_HFILE); Assert (SYS_WIN16 == 0 && SYS_WIN32 == 1 && SYS_MAC == 2 && SysKind <= SYS_MAX); HOut(szHeadFile); // output file header HOutF(typlib.szLibName); // output type library name HOut(" */\n\n#ifndef _"); // output: #ifndef _<libname>_H_ HOutF(typlib.szLibName); // #define _<libname>_H_ HOut("_H_\n#define _"); HOutF(typlib.szLibName); HOut("_H_\n"); HOutGuid(&typlib.attr, szHeadGuidLIBID, typlib.szLibName); if (fSpecifiedInterCC) { HOut(szCCHeader); } if (typlib.pEntry) { pEntry = (LPENTRY)ListFirst(typlib.pEntry); // point to first entry #pragma warning(disable:4127) while (TRUE) #pragma warning(default:4127) { switch (pEntry->type.tentrykind & ~tFORWARD) { case tTYPEDEF: HOutTypedef(&pEntry->type); break; case tENUM: HOutEnum(&pEntry->type); break; case tSTRUCT: case tUNION: HOutStructUnion(&pEntry->type); break; case tMODULE: HOutModule(pEntry); break; case tCOCLASS: HOutCoclass(pEntry); break; case tINTERFACE: case tDISPINTER: HOutInterface(pEntry); // fall through case tINTRINSIC: case tREF: break; // nothing to output #ifdef DEBUG default: if (pEntry->type.tentrykind & tIMPORTED) break; // noting to output for imported types Assert(FALSE); #endif //DEBUG } // advance to next entry if not all done if (pEntry == (LPENTRY)ListLast(typlib.pEntry)) break; // exit if all done pEntry = (LPENTRY)pEntry->type.pNext; } // WHILE } HOut("\n#endif\n"); fclose(hHFile); // done writing .H file hHFile = NULL; // close done // check for possible alignment problems if (iAlignMax != iAlignDef) ParseError(WARN_STRANGE_ALIGNMENT); #ifdef PROFILE printf("\n\ntotal functions: %d\n", cFuncsTotal); printf("total function args: %d\n", cArgsTotal); printf("total variables: %d\n", cVarsTotal); ParseError(ERR_OM); // bogus early quit #endif //PROFILE }