32位程序调用16位的DLL和反过来,能给俺点相关的资料吗?谢谢
邮箱:[email protected]

解决方案 »

  1.   

    type//Dos File headerDosFileHeader = recordID: Word;LengthMod: Word;LengthDIV: Word;Segments: Word;ParagraphsHeader: Word;MinHeader: Word;MaxHeader: Word;SPReg: Word;CheckSumHeader: Word;IPReg: Word;CodeSeg: Word;RelocTable: Word;OverlayNumber: Word;end;//Windows File headerWindowsFileHeader = recordID: longint;Machine: Word;NumberOfObjects: Word;TimeDateStamp: DWord;PointerToSymbolTable: LongInt;NumberofSymbols: LongInt;SizeOfOptionalHeader: Word;Characteristics: Word;//followed by advanced NT/Win95 Header (portable executable)Magic: Word;MajorVersion: Byte;MinorVersion: Byte;SizeOfCode: Longint;SizeOfInitializedDate: Longint;SizeOfUninitializedData: LongInt;AddressOfEntryPoint: LongInt;BaseOfCode: LongInt;BaseOfData: LongInt;ImageBase: LongInt;SectionAlignment: LongInt;FileAlignment: Longint;OSMajor: Word;OSMinor: Word;UserMajor: Word;UserMinor: Word;OSMajorSub: Word;OSMinorSub: Word;Reserved1: LongInt;SizeOfImage: Longint;SizeOfHeader: Longint;CheckSum: Longint;Subsystem: word;DLLCharacteristics: word;SizeOfStackReserve: Longint;SizeOfStackCommit: Longint;SizeOfHeapReserve: longint;SizeOfHeapCommit: Longint;loaderFlags: Longint;NumberofRVAandSizes: LongInt;end;//Entry-struct in object tableObjectTableEntry = recordObjectName: array[0..7] of Byte;VirtualSize: Longint;VirtualAddress: Longint;SizeOfRawData: longInt;PointerToRawData: longint;PointerToRelocations: LongInt;PointerToLineNumbers: LongInt;NumberOfRelocations: Word;NumberOfLineNumbers: Word;Characteristics: LongInt;end;//Structure of export-tableExportTableHeader = recordCharacteristics: Longint;TimeDateStamp: Longint;MajorVersion: Word;MinorVersion: Word;Name: LongInt;base: Longint;NumberofFunctions: Longint;NumberofNames: Longint;pAddressofFunctions: Longint;pAddressofNames: Longint;pAddressOfNameOrdinals: Longint;end;//declarations for undocumented functionsfBeep = function (Frq, Time: Longint):boolean; stdcall;fVxDCall = function (Service: Longint; Ax, CX: Longint): Longint; stdcall;fLoadLibrary16 = function (LibName: PChar): THandle; stdcall;fFreeLibrary16 = function (Handle: integer): integer; stdcall;fGetProcAddress16 = function (handle: integer; ProcName: PChar): pointer; stdcall;function GetProcAddress32(LibName: PChar; Ordinal: integer): pointer;procedure QT_Thunk; cdecl; external kernel32 name 'QT_Thunk'; function GetProcAddress32(LibName: PChar; Ordinal: integer): pointer;varAddressOfFunction: ^Longint;VirtualFunctionAddress: ^Longint;WindowsHeaderOffset: ^Word;ModuleHandle: THandle;i: integer;ObjectName: PChar;FirstObjectAddress: Longint;WindowsHeader: ^WindowsFileHeader;ObjectEntry: ^ObjectTableEntry;ExportObject: ^ObjectTableEntry;ExportTable: ^ExportTableHeader;begin//Get module address (virtual) in memoryModuleHandle := GetModuleHandle(LibName);WindowsHeaderOffset := ptr(ModuleHandle +$3C);WindowsHeader := ptr(ModuleHandle + WindowsHeaderOffset^);//find export tablefor i := 0 to WindowsHeader^.NumberofObjects-1 dobeginFirstObjectAddress := ModuleHandle + WindowsHeaderOffset^ + SizeOf(WindowsHeader^) +WindowsHeader^.NumberofRVAandSizes*8 + i*SizeOf(ObjectEntry^);ObjectName := ptr(FirstObjectAddress);if ObjectName = '.edata' thenbeginExportObject := ptr(FirstObjectAddress);ExportTable := ptr(ModuleHandle + ExportObject^.VirtualAddress);end;end;//getting function addressVirtualFunctionAddress := ptr( ModuleHandle + ExportTable^.pAddressOfFunctions +(Ordinal-ExportTable^.Base)*4);//...and backAddressOfFunction := ptr(WindowsHeader^.ImageBase + VirtualFunctionAddress^);GetProcAddress32 := AddressOfFunction;end;amo (1999-10-25 11:03:39)
      

  2.   


    补充对Keyes的代码的说明:The intention of this posting is to show a way of how to access 16 bitDLLs out of an application developed in Delphi 2. A few days ago iposted a message in delphi.misc to show the usage of undocumentedfunctions inside Kernel32.dll. Especially there are four of interest:LoadLibrary16, GetProcAddress16, FreeLibrary16 and VxDCall0. With thehelp of these functions, you can load and free 16bit libraries and getthe virtual address of a procedure inside a dll.But there are some problems: kernel32 does not export undocumentedfunctions by name or ordinal. The only way to solve this was to readand understand the internal PE(portable executable) formatspecification. The PE format is used by 32bit apps and dlls. Byexamining this format, you will find an export table with the absoluteoffset of each function inside. Combined with the virtual moduleaddress in memory, you get the virtual starting point of anundocumented function. This does the function GetProcAdress32.The next problem: 16bit functions/apps are using a different kind ofaddressing (segment:offset) and have their own address space/stackinside Win95, which "emulates" a 16bit os. To call a 16bit functionout of a 32bit application, you have to "build" a 16bit stack and todo some other work ;-) . This does a kernel32 function named'QT_Thunk'. With the help of some lines of inline assembler, you pushyour arguments on the stack, push the virtual address of your 16bitfunction in the register edx and call QT_Thunk. The return values canbe found in several registers. The example uses theGetFreeSystemResources inside (the 16bit) user.exe and works fine.Some comments: This source is free but without any guarantees! I wouldlike to get responses about the implementation of my code in yours.The implementation of the thunk mechanism inside the asm statement wastaken from an example of Tempest Software, but i do not accept theircopyright, since their piece of code does *not* work and uses nospecial algorithms (only some WIN API calls)! The information aboutaccessing undocumented functions was taken from Andrew Schulmans"Undocumented Windows" and "Unautherized Windows". Great books! If youhave problems with getting this code to run mail me, i will send you acopy of my complete source as attachment.dxd (1999-10-27 9:27:20)谁能写的明白些?如是C函数INT2 DllExport Init_search(char *sj_drivestr,char *ck_drivestr,char *basestr);的Delphi描述如下varhInst16: THandle;GFSR: Pointer;function D16_HR_init_search(IndexDir,CkDir,BaseDir:string):Integer;varpp:DWORD;p:Pointer; fm:THandle;ThunkTrash: array[0..$20] of Word;ans:WORD;iDir,cDir,bDIr:PChar;hi1,hi2,hi3,lo1,lo2,lo3:WORD;beginResult:=-1;if Win32Platform = VER_PLATFORM_WIN32_NT then Exit; StrPcopy( iDir,IndexDir );StrPcopy( cDir,CKDir );StrPcopy( bDir,BaseDir );ThunkTrash[0] := hInst16;hInst16 := LoadLibrary16('SAPI16.DLL');if hInst16 < 32 thenraise Exception.Create('Cannot load SAPI16.DLL');// FreeLibrary16(hInst16);GFSR := GetProcAddress16(hInst16, 'HR_init_search');if GFSR = nil thenraise Exception.Create('Get address Error of HR_init_search');hi1 := WORD((DWORD(iDir) shr 16) and $ffff );lo1 := WORD(DWORD(iDir) and $ffff );hi2 := WORD((DWORD(CDir) shr 16) and $ffff );lo2 := WORD(DWORD(CDir) and $ffff );hi3 := WORD((DWORD(BDir) shr 16) and $ffff );lo3 := WORD(DWORD(BDir) and $ffff );asm //Thunk down to USER.EXEpush hi1push lo1push hi2push lo2push hi3push lo3mov edx, GFSR { load 16-bit procedure pointer }call QT_Thunk { call thunk }mov ans, ax { save the result }end;{ Free the library }FreeLibrary16(hInst16);if ans > 0 then Result:=0;end;执行总是出错,请诊治!Another_eYes (2000-9-4 21:48:09)瞎猜的:32位的call指令将32位返回地址地址压栈. 而16位程序取参数一般是从[bp-2]开始的而此时真正的参数应当在[ebp-4]位置, 故出错.所以我猜想可否call指令替换成PUSH ESP // ESP能直接压栈吗? 忘了MOV EBP, ESPADD EBP,2JMP QT_Thunk Another_eYes (2000-9-4 21:55:48)错了错了, 记错了. 呵呵 ESP是堆栈寄存器不是指令寄存器.而且上述理解有误.问题应当出在返回后的堆栈上. CALL时32位压栈, 16位程序的RET只出栈了16位,因此返回后堆栈需要调整CALL后加一句POP DX (或者 ADD SP, 2)试试
    转给你看看。