source: trunk/src/win32k/test/fake.c@ 4172

Last change on this file since 4172 was 4164, checked in by bird, 25 years ago

Merged in the Grace branch. New Win32k!

File size: 58.3 KB
Line 
1/* $Id: fake.c,v 1.2 2000-09-02 21:08:20 bird Exp $
2 *
3 * Fake stubs for the ldr and kernel functions we imports or overloads.
4 *
5 * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants And Macros *
13*******************************************************************************/
14#define INCL_BASE
15#define FOR_EXEHDR 1 /* To make all object flags OBJ???. */
16#define INCL_OS2KRNL_ALL
17#define DWORD ULONG
18#define WORD USHORT
19
20#define DUMMY() int dummy; dummy = 0; dummy = dummy + 1;
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#include <os2.h>
26#include <newexe.h> /* OS/2 NE structs and definitions. */
27#include <exe386.h> /* OS/2 LX structs and definitions. */
28
29#include <string.h>
30
31#include "devSegDf.h" /* Win32k segment definitions. */
32
33#include "log.h"
34#include "OS2Krnl.h"
35#include "dev32.h"
36#include "ldrcalls.h"
37#include "test.h"
38#include "macros.h"
39
40#include "malloc.h"
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45typedef struct ldrrei_s /* #memb 7 size 20 (0x014) - from 14040W4 kernel.sdf */
46{
47 PVOID ei_startaddr; /* off: 0(00) size: 4(04) */
48 PVOID ei_stackaddr; /* off: 4(04) size: 4(04) */
49 PVOID ei_pstackmax; /* off: 8(08) size: 4(04) */
50 USHORT ei_ds; /* off: 12(0c) size: 2(02) */
51 USHORT ei_stacksize; /* off: 14(0e) size: 2(02) */
52 USHORT ei_heapsize; /* off: 16(10) size: 2(02) */
53 USHORT ei_loadtype; /* off: 18(12) size: 2(02) */
54} ldrrei_t;
55
56
57
58/*******************************************************************************
59* Global Variables *
60*******************************************************************************/
61/*
62 * Pointer to the loader semaphore.
63 */
64KSEMMTX fakeLDRSem;
65
66CHAR szBeginLibPath[1024];
67CHAR szEndLibPath[1024];
68CHAR szLibPath[1024];
69PSZ fakeLDRLibPath = &szLibPath[0];
70
71CHAR szldrpFileNameBuf[CCHMAXPATH];
72PSZ fakeldrpFileNameBuf = &szldrpFileNameBuf[0];
73
74static CHAR achHeaderBuffer[256]; /* Buffer to read exe header into. */
75PVOID pheaderbuf = &achHeaderBuffer[0];
76
77
78/*
79 * table use by fakeldrMTEValidatePtrs.
80 */
81USHORT validatetbl[] =
82{
83 FIELDOFFSET(SMTE, smte_objmap),
84 FIELDOFFSET(SMTE, smte_rsrctab),
85 FIELDOFFSET(SMTE, smte_restab),
86 FIELDOFFSET(SMTE, smte_enttab),
87 FIELDOFFSET(SMTE, smte_fpagetab),
88 FIELDOFFSET(SMTE, smte_frectab),
89 FIELDOFFSET(SMTE, smte_impmod),
90 FIELDOFFSET(SMTE, smte_impproc),
91 0xDEAD
92};
93
94
95/*******************************************************************************
96* External Functions *
97*******************************************************************************/
98#define QHINF_EXEINFO 1 /* NE exeinfo. */
99#define QHINF_READRSRCTBL 2 /* Reads from the resource table. */
100#define QHINF_READFILE 3 /* Reads from the executable file. */
101#define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
102#define QHINF_LIBPATH 5 /* Gets the entire libpath. */
103#define QHINF_FIXENTRY 6 /* NE only */
104#define QHINF_STE 7 /* NE only */
105#define QHINF_MAPSEL 8 /* NE only */
106
107APIRET APIENTRY DosQueryHeaderInfo(HMODULE hmod,
108 ULONG ulIndex,
109 PVOID pvBuffer,
110 ULONG cbBuffer,
111 ULONG ulSubFunction);
112
113/*******************************************************************************
114* Internal Functions *
115*******************************************************************************/
116ULONG LDRCALL fakeLDRLoadExe(PSZ pszFilename, ldrrei_t *pEI);
117ULONG LDRCALL fakeldrGetModule(PSZ pszFilename, ULONG ul);
118ULONG LDRCALL fakeldrGetMte(PCHAR pachFilename, USHORT cchFilename, UCHAR fchType, UCHAR fchClass, PPMTE ppmte);
119ULONG LDRCALL fakeldrOpenNewExe(PCHAR pachFilename, USHORT cchFilename, ldrlv_t *plv, PUSHORT pus);
120ULONG LDRCALL fakeldrCreateMte(struct e32_exe * pe32, ldrlv_t *plv);
121ULONG LDRCALL fakeldrLoadImports(PMTE pmte);
122VOID LDRCALL fakeldrUCaseString(PCHAR pachString, USHORT cchString);
123ULONG LDRCALL fakeldrMTEValidatePtrs(PSMTE psmte, ULONG ulMaxAddr, ULONG off);
124unsigned short getSlot(void);
125
126
127
128/**
129 * Initiate workers (imported kernel functions / vars)
130 * @status partially implemented.
131 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
132 */
133void workersinit(void)
134{
135 APIRET rc;
136
137 /*
138 * Make code writable.
139 */
140 DosSetMem(&CODE16START, &CODE16END - &CODE16START, PAG_WRITE | PAG_READ);
141 DosSetMem(&CODE32START, &CODE32END - &CODE32START, PAG_WRITE | PAG_READ);
142
143 /*
144 * Loader semaphore
145 */
146 fakeKSEMInit((PKSEM)(void*)&fakeLDRSem, KSEM_MUTEX, KSEM_DEFAULT);
147
148 /*
149 * Intra process semaphore.
150 */
151 fakeKSEMInit((PKSEM)(void*)&fakeptda_ptdasem, KSEM_MUTEX, KSEM_DEFAULT);
152
153 /*
154 * LIBPaths
155 */
156 rc = DosQueryExtLIBPATH(szBeginLibPath, BEGIN_LIBPATH);
157 rc = DosQueryHeaderInfo(NULLHANDLE, 0, szLibPath, sizeof(szLibPath), QHINF_LIBPATH);
158 rc = DosQueryExtLIBPATH(szEndLibPath, END_LIBPATH);
159
160 rc = rc;
161}
162
163
164/**
165 * Fake ldrClose
166 * @returns OS2 return code.
167 * @param hFile Filehandle of the file to be closed.
168 * @status completely impelemented.
169 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
170 * @remark
171 */
172ULONG LDRCALL fakeldrClose(SFN hFile)
173{
174 APIRET rc;
175 BOOL f32Stack = ((int)&hFile > 0x10000);
176
177 if (!f32Stack) ThunkStack16To32();
178
179 rc = DosClose(hFile);
180
181 if (!f32Stack) ThunkStack32To16();
182
183 printf("fakeldrClose: hFile = 0x%04x, rc = %d\n", hFile, rc);
184
185 return rc;
186}
187
188/**
189 * Fake ldrOpen.
190 * @returns OS2 return code.
191 * @param phFile Pointer to return handle.
192 * @param pszFilename Pointer to filename.
193 * @param pfl Pointer to media flags? *pfl is set to zero!
194 * @sketch Do a DosOpen on the filename.
195 * @status partially implemented.
196 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
197 * @remark
198 */
199ULONG LDRCALL fakeldrOpen(PSFN phFile, PSZ pszFilename, PULONG pfl)
200{
201 ULONG ulAction;
202 HFILE hFile;
203 APIRET rc;
204 BOOL f32Stack = ((int)&hFile > 0x10000);
205
206 if (!f32Stack) ThunkStack16To32();
207
208 hFile = 0;
209 ulAction = 0;
210 rc = DosOpen(pszFilename, &hFile, &ulAction, 0, FILE_NORMAL,
211 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
212 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE,
213 NULL);
214 if (rc == NO_ERROR)
215 {
216 *phFile = (USHORT)hFile;
217 if (pfl != NULL)
218 *pfl = 0;
219 rc = DosQueryPathInfo(pszFilename, FIL_QUERYFULLNAME, fakeldrpFileNameBuf, CCHMAXPATH);
220 rc = NO_ERROR;
221 }
222
223 if (!f32Stack) ThunkStack32To16();
224
225 printf("fakeldrOpen: phFile = %p; *phFile = 0x%04x, pszFilename = %s, pfl = %p, rc = %d\n",
226 phFile, *phFile, pszFilename, pfl, rc);
227
228 return rc;
229}
230
231
232/**
233 * ldrRead fake.
234 * @returns OS/2 return code. (NO_ERROR on success...)
235 * @param hFile Handle to file.
236 * @param ulOffset Offset in the file to start reading at.
237 * @param pvBuffer Pointer to output buffer.
238 * @param fpBuffer Far pointer to buffer. (ignored)
239 * @param cbToRead Count of bytes to read.
240 * @param pMTE MTE pointer (used for caching?)
241 *
242 * @sketch Set Change filepointer to ulOffset.
243 * Read cbToRead into pvBufer.
244 * @status completely tested.
245 * @author knut st. osmundsen
246 * @remark
247 */
248ULONG LDRCALL fakeldrRead(SFN hFile, ULONG ulOffset, PVOID pvBuffer, ULONG fpBuffer, ULONG cbToRead, PMTE pMTE)
249{
250 ULONG cbRead,
251 ulMoved;
252 APIRET rc;
253 BOOL f32Stack = ((int)&hFile > 0x10000);
254
255 if (!f32Stack) ThunkStack16To32();
256
257 rc = DosSetFilePtr(hFile, ulOffset, FILE_BEGIN, &ulMoved);
258 if (rc == NO_ERROR)
259 rc = DosRead(hFile, pvBuffer, cbToRead, &cbRead);
260 else
261 kprintf(("fakeldrRead: DosSetFilePtr(hfile, 0x%08x(%d),..) failed with rc = %d.\n",
262 ulOffset, ulOffset, rc));
263
264 if (!f32Stack) ThunkStack32To16();
265
266 printf("fakeldrRead: hFile = 0x%04x, ulOffset = 0x%08x, pvBuffer = %p, fpBuffer = 0x%08x, cbToRead = 0x%08x, pMte = %p, rc = %d\n",
267 hFile, ulOffset, pvBuffer, fpBuffer, cbToRead, pMTE, rc);
268
269 return rc;
270}
271
272
273/**
274 * LDRQAppType faker.
275 * @returns OS/2 return code.
276 * @param pszFilename Pointer to executable to query app type for.
277 * @param pul Pointer to flag variable to return apptype flags in.
278 * @sketch
279 * @status stub.
280 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
281 * @remark
282 */
283ULONG LDRCALL fakeLDRQAppType(PSZ pszFilename, PULONG pul)
284{
285 DUMMY();
286 printf("fakeLDRQAppType: pszFilename = %s, pul = %p, rc = 0\n", pszFilename, pul);
287 return NO_ERROR;
288}
289
290
291/**
292 * ldrEnum32bitRelRecs
293 * @param pMTE Pointer to MTE for this module.
294 * @param iObject Object index. 0-based!
295 * @param iPageTabl Page index. 0-based!
296 * @param pvPage Pointer to page buffer.
297 * @param ulPageAddress Note! Page is not present.
298 * @param pPTDA
299 * @status stub
300 */
301ULONG LDRCALL fakeldrEnum32bitRelRecs(
302 PMTE pMTE,
303 ULONG iObject,
304 ULONG iPageTable,
305 PVOID pvPage,
306 ULONG ulPageAddress,
307 PVOID pvPTDA
308 )
309{
310 DUMMY();
311 printf("fakeldrEnum32bitRelRecs: pMTE = %p, iObject = 0x%08x, iPageTable = 0x%08x, pvPage = 0x%08x, ulPageAddress = 0x%08x, pvPTDA = %p\n",
312 pMTE, iObject, iPageTable, pvPage, ulPageAddress, pvPTDA);
313
314 return NO_ERROR;
315}
316
317/**
318 * Opens a given file.
319 * @returns NO_ERROR on success. OS/2 error code on error.
320 * @param pszFilename Pointer to filename.
321 * @param flOpenFlags Open flags. (similar to DosOpen)
322 * @param fsOpenMode Open mode flags. (similar to DosOpen)
323 * @param phFile Pointer to filehandle.
324 * @param pulsomething 16-bit near (?) pointer to a variable - unknown. NULL is allowed. EA?
325 */
326APIRET KRNLCALL fakeIOSftOpen(
327 PSZ pszFilename,
328 ULONG flOpenFlags,
329 ULONG fsOpenMode,
330 PSFN phFile,
331 PULONG pulsomething
332 )
333{
334 ULONG ulAction;
335 HFILE hFile;
336 APIRET rc;
337 BOOL f32Stack = ((int)&hFile > 0x10000);
338
339 if (!f32Stack) ThunkStack16To32();
340
341 hFile = 0;
342 ulAction = 0;
343 rc = DosOpen(pszFilename, &hFile, &ulAction, 0, FILE_NORMAL,
344 flOpenFlags,
345 fsOpenMode,
346 NULL);
347 if (rc == NO_ERROR)
348 *phFile = (USHORT)hFile;
349
350 if (!f32Stack) ThunkStack32To16();
351
352 printf("fakeIOSftOpen: pszFilename = %s, flOpenFlags = 0x%08x, fsOpenMode = 0x%08x, phFile = %p; *phFile = 0x%04, pulsomething = %p, rc = %d\n",
353 pszFilename, flOpenFlags, fsOpenMode, phFile, *phFile, pulsomething, rc);
354
355 return rc;
356}
357
358
359/**
360 * Closes the specified file.
361 * @returns NO_ERROR on success. OS/2 error code on error.
362 * @param hFile File handle - System File Number.
363 */
364APIRET KRNLCALL fakeIOSftClose(
365 SFN hFile
366 )
367{
368 APIRET rc;
369 BOOL f32Stack = ((int)&hFile > 0x10000);
370
371 if (!f32Stack) ThunkStack16To32();
372
373 rc = DosClose(hFile);
374
375 if (!f32Stack) ThunkStack32To16();
376
377 printf("fakeIOSftClose: hFile = 0x%04, rc = %d\n",
378 hFile, rc);
379
380 return rc;
381}
382
383
384/**
385 * Probably this function will expand a relative path to a full path.
386 * @returns NO_ERROR on success. OS/2 error code on error.
387 * @param pszPath Pointer to path to expand. Contains the full path upon return. (?)
388 * This buffer should probably be of CCHMAXPATH length.
389 * @status completely implemented.
390 */
391APIRET KRNLCALL fakeIOSftTransPath(
392 PSZ pszPath
393 )
394{
395 char szBuffer[CCHMAXPATH];
396 APIRET rc;
397 BOOL f32Stack = ((int)&pszPath > 0x10000);
398
399 if (!f32Stack) ThunkStack16To32();
400
401 rc = DosQueryPathInfo(pszPath, FIL_QUERYFULLNAME, &szBuffer, sizeof(szBuffer));
402 printf("fakeIOSftTransPath: pszPath(in) = %s, pszPath(out) = %s, rc = %d\n",
403 pszPath, szBuffer, rc);
404 if (rc == NO_ERROR)
405 strcpy(pszPath, szBuffer);
406 else
407 kprintf(("fakeIOSftTransPath: DosQueryPathInfo failed with rc=%d\n", rc));
408
409
410 if (!f32Stack) ThunkStack32To16();
411
412 return rc;
413}
414
415
416/**
417 * Read at a given offset in the a file.
418 * @returns NO_ERROR on success. OS/2 error code on error.
419 * @param hFile File handle - System File Number.
420 * @param pcbActual Pointer to variable which upon input holds the number
421 * of bytes to read, on output the actual number of bytes read.
422 * @param pvBuffer Pointer to the read buffer.
423 * @param fpBuffer 16 far pointer to buffer. (ignored)
424 * @param ulOffset File offset to read from. (0=start of file)
425 */
426APIRET KRNLCALL fakeIOSftReadAt(
427 SFN hFile,
428 PULONG pcbActual,
429 PVOID pvBuffer,
430 ULONG fpBuffer,
431 ULONG ulOffset
432 )
433{
434 ULONG ulMoved;
435 APIRET rc;
436 BOOL f32Stack = ((int)&hFile > 0x10000);
437
438 if (!f32Stack) ThunkStack16To32();
439
440 rc = DosSetFilePtr(hFile, ulOffset, FILE_BEGIN, &ulMoved);
441 if (rc == NO_ERROR)
442 rc = DosRead(hFile, pvBuffer, *pcbActual, pcbActual);
443 else
444 kprintf(("fakeIOSftReadAt: DosSetFilePtr(hfile, 0x%08x(%d),..) failed with rc = %d.",
445 ulOffset, ulOffset, rc));
446
447 if (!f32Stack) ThunkStack32To16();
448
449 printf("fakeIOSftReadAt: hFile = 0x%04, pcbActual = %p; *pcbActual = 0x%08x, pvBuffer = %p, fpBuffer = %x, ulOffset = 0x%08x, rc = %d\n",
450 hFile, pcbActual, pvBuffer, fpBuffer, ulOffset, rc);
451
452 return rc;
453}
454
455
456/**
457 * Write at a given offset in the a file.
458 * @returns NO_ERROR on success. OS/2 error code on error.
459 * @param hFile File handle - System File Number.
460 * @param pcbActual Pointer to variable which upon input holds the number
461 * of bytes to write, on output the actual number of bytes write.
462 * @param pvBuffer Pointer to the write buffer.
463 * @param fpBuffer 16 far pointer to buffer. (ignored)
464 * @param ulOffset File offset to write from. (0=start of file)
465 */
466APIRET KRNLCALL fakeIOSftWriteAt(
467 SFN hFile,
468 PULONG pcbActual,
469 PVOID pvBuffer,
470 ULONG fpBuffer,
471 ULONG ulOffset
472 )
473{
474 ULONG ulMoved;
475 APIRET rc;
476 BOOL f32Stack = ((int)&hFile > 0x10000);
477
478 if (!f32Stack) ThunkStack16To32();
479
480 rc = DosSetFilePtr(hFile, ulOffset, FILE_BEGIN, &ulMoved);
481 if (rc == NO_ERROR)
482 rc = DosWrite(hFile, pvBuffer, *pcbActual, pcbActual);
483 else
484 kprintf(("fakeIOSftWriteAt: DosSetFilePtr(hfile, 0x%08x(%d),..) failed with rc = %d.",
485 ulOffset, ulOffset, rc));
486
487 if (!f32Stack) ThunkStack32To16();
488
489 printf("fakeIOSftWriteAt: hFile = 0x%04, pcbActual = %p; *pcbActual = 0x%08x, pvBuffer = %p, fpBuffer = %x, ulOffset = 0x%08x, rc = %d\n",
490 hFile, pcbActual, pvBuffer, fpBuffer, ulOffset, rc);
491
492 return rc;
493}
494
495
496/**
497 * Gets the filesize.
498 * @returns NO_ERROR on success; OS/2 error code on error.
499 * @param hFile File handle - System File Number.
500 * @param pcbFile Pointer to ULONG which will hold the file size upon return.
501 */
502APIRET KRNLCALL fakeSftFileSize(
503 SFN hFile,
504 PULONG pcbFile
505 )
506{
507 FILESTATUS3 fsts3;
508 APIRET rc;
509 BOOL f32Stack = ((int)&hFile > 0x10000);
510
511 if (!f32Stack) ThunkStack16To32();
512
513 rc = DosQueryFileInfo(hFile,
514 FIL_STANDARD,
515 &fsts3,
516 sizeof(fsts3));
517 if (rc == NO_ERROR)
518 *pcbFile = fsts3.cbFile;
519 else
520 kprintf(("fakeSftFileSize: DosQueryFileInfo failed with rc=%d\n", rc));
521
522 if (!f32Stack) ThunkStack32To16();
523
524 printf("fakeSftFileSize: hFile = 0x%04x, pcbFile = %p; *pcbFile = 0x%08x, rc = %d\n",
525 hFile, pcbFile, *pcbFile, rc);
526
527 return rc;
528}
529
530
531/**
532 * @status stub
533 */
534HMTE KRNLCALL fakeVMGetOwner(
535 ULONG ulCS,
536 ULONG ulEIP)
537{
538 DUMMY();
539
540 printf("fakeVMGetOwner: ulCS = 0x%04x, ulEiP = 0x%08x, rc = %d\n",
541 ulCS, ulEIP, 0);
542
543 return 0;
544}
545
546
547/**
548 * @status stub
549 */
550APIRET KRNLCALL fakeVMAllocMem(
551 ULONG cbSize,
552 ULONG cbCommit,
553 ULONG flFlags1,
554 HPTDA hPTDA,
555 USHORT usVMOwnerId,
556 HMTE hMTE,
557 ULONG flFlags2,
558 ULONG SomeArg2,
559 PVMAC pvmac)
560{
561 DUMMY();
562 printf("fakeVMAllocMem: cbSize = 0x%08x, cbCommit = 0x%08x, flFlags1 = 0x%08x, hPTDA = 0x%04x, usVMOwnerId = 0x%04x, hMTE = 0x%04x, flFlags2 = 0x%08x, SomeArg2 = 0x%08x, pvmac = %p, rc = %d\n",
563 cbSize, cbCommit, flFlags1, hPTDA, usVMOwnerId, hMTE, flFlags2, SomeArg2, pvmac, 0);
564
565 return ERROR_NOT_SUPPORTED;
566}
567
568
569/**
570 * @status stub
571 * @remark Used by environment stuff...
572 */
573APIRET KRNLCALL fakeVMObjHandleInfo(
574 USHORT usHob,
575 PULONG pulAddr,
576 PUSHORT pushPTDA)
577{
578 APIRET rc = NO_ERROR;
579 BOOL f32Stack = ((int)&usHob > 0x10000);
580
581 if (!f32Stack) ThunkStack16To32();
582
583 if (pulAddr > (PULONG)0x10000 && pushPTDA > (PUSHORT)0x10000)
584 {
585 PTIB pTib;
586 PPIB pPib;
587 DosGetInfoBlocks(&pTib, &pPib);
588 switch (usHob)
589 {
590 case 1: *pulAddr = (ULONG)pPib->pib_pchenv; break; //PTDA environ (fakea.asm)
591 default:
592 printf("fakeVMObjHandleInfo: Invalid handle! (usHob=0x%#4x)\n", usHob);
593 rc = ERROR_INVALID_HANDLE;
594 }
595 *pushPTDA = 10; //dummy
596 }
597 else
598 rc = ERROR_INVALID_PARAMETER;
599
600 if (!f32Stack) ThunkStack32To16();
601
602 printf("fakeVMObjHandleInfo: usHob = 0x%04x, pulAddr = %p, pushPTDA = %p, rc = %d\n",
603 usHob, pulAddr, pushPTDA, rc);
604 return rc;
605}
606
607
608/**
609 * myldrOpenPath - opens file eventually searching loader specific paths
610 *
611 * @returns OS2 return code.
612 * pLdrLv->lv_sfn is set to filename handle.
613 * @param pachFilename Pointer to modulename. Not zero terminated?
614 * @param cchFilename Modulename length.
615 * @param plv Loader local variables? (Struct from KERNEL.SDF)
616 * @param pful Pointer to flags which are passed on to ldrOpen.
617 * @status stub
618 */
619ULONG LDRCALL fakeldrOpenPath(PCHAR pachFilename, USHORT cchFilename, ldrlv_t *plv, PULONG pful)
620{
621 static char szPath[1024]; /* Path buffer. Used to store pathlists. 1024 should be enough */
622 /* for LIBPATH (which at had a limit of ca. 750 chars). */
623 static char sz[CCHMAXPATH]; /* Filename/path buffer. (Normally used to build filenames */
624 /* which are passed in as search experessions to DosFindFirst.) */
625
626 APIRET rc; /* Return value. (Pessimistic attitude! Init it to FALSE...) */
627
628 printf("fakeldrOpenPath: *entry* pachFilename = %.*s, cchFilename = %d, plv = %p, pful = %p\n",
629 cchFilename, pachFilename, cchFilename, plv, pful);
630
631 if (plv->lv_class != CLASS_GLOBAL)
632 rc = fakeldrOpen(&plv->lv_sfn, pachFilename, pful);
633 else
634 {
635 int iPath; /* Current path or pathlist being examined. This is the loop */
636 /* variable looping on the FINDDLL_* defines. */
637
638 /* These defines sets the order the paths and pathlists are examined. */
639 #define FINDDLL_BEGINLIBPATH 7
640 #define FINDDLL_LIBPATH 8
641 #define FINDDLL_ENDLIBPATH 9
642 #define FINDDLL_FIRST FINDDLL_BEGINLIBPATH
643 #define FINDDLL_LAST FINDDLL_ENDLIBPATH
644
645 /*
646 * Remove DLL extention from the filename.
647 */
648 if (cchFilename > 4 && !strncmp(&pachFilename[cchFilename - 4], ".DLL", 4))
649 {
650 cchFilename -= 4;
651 pachFilename[cchFilename] = '\0';
652 }
653
654 /** @sketch
655 * Loop thru the paths and pathlists searching them for the filename.
656 */
657 rc = ERROR_FILE_NOT_FOUND;
658 for (iPath = FINDDLL_FIRST; iPath <= FINDDLL_LAST; iPath++)
659 {
660 const char * pszPath; /* Pointer to the path being examined. */
661
662 /** @sketch Get the path/dir to examin. (This is determined by the value if iPath.) */
663 switch (iPath)
664 {
665 case FINDDLL_BEGINLIBPATH:
666 rc = DosQueryExtLIBPATH(szPath, BEGIN_LIBPATH);
667 break;
668 case FINDDLL_LIBPATH:
669 rc = DosQueryHeaderInfo(NULLHANDLE, 0, szPath, sizeof(szPath), QHINF_LIBPATH);
670 break;
671 case FINDDLL_ENDLIBPATH:
672 rc = DosQueryExtLIBPATH(szPath, END_LIBPATH);
673 break;
674 default: /* !internalerror! */
675 return ERROR_FILE_NOT_FOUND;
676 }
677 if (rc != NO_ERROR)
678 {
679 printf("fakeldrOpenPath: DosQueryExtLIBPATH/DosQueryHeadInfo failed with rc=%d, iPath=%d", rc, iPath);
680 continue;
681 }
682 pszPath = szPath;
683
684
685 /** @sketch
686 * pszPath is now set to the pathlist to be searched.
687 * So we'll loop thru all the paths in the list.
688 */
689 while (pszPath != NULL && *pszPath != '\0')
690 {
691 char * pszNext; /* Pointer to the next pathlist path */
692 int cch; /* Length of path (including the slash after the slash is added). */
693
694 /** @sketch
695 * Find the end of the path.
696 * Copy the path into the sz buffer.
697 * Set pszNext.
698 */
699 pszNext = strchr(pszPath, ';');
700 if (pszNext != NULL)
701 {
702 cch = pszNext - pszPath;
703 pszNext++;
704 }
705 else
706 cch = strlen(pszPath);
707
708 if (cch + cchFilename + 1 >= sizeof(sz)) /* assertion */
709 {
710 printf("fakeldrOpenPath: cch (%d) + cchFilename (%d) + 1 < sizeof(plv->sz) (%d) - paths too long!, iPath=%d",
711 cch, cchFilename, sizeof(sz), iPath);
712 pszPath = pszNext;
713 continue;
714 }
715 memcpy(sz, pszPath, cch);
716
717 /** @sketch
718 * Add a '\\' and the filename (pszFullname) to the path;
719 * then we'll have a fullpath.
720 */
721 sz[cch++] = '\\';
722 memcpy(&sz[cch], pachFilename, cchFilename);
723 memcpy(&sz[cch + cchFilename], ".DLL", 5);
724
725 rc = fakeldrOpen(&plv->lv_sfn, sz, pful);
726 switch (rc)
727 {
728 case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: case ERROR_ACCESS_DENIED: case ERROR_INVALID_ACCESS:
729 case ERROR_INVALID_DRIVE: case ERROR_NOT_DOS_DISK: case ERROR_REM_NOT_LIST: case ERROR_BAD_NETPATH:
730 case ERROR_NETWORK_BUSY: case ERROR_DEV_NOT_EXIST: case ERROR_TOO_MANY_CMDS: case ERROR_ADAP_HDW_ERR:
731 case ERROR_UNEXP_NET_ERR: case ERROR_BAD_REM_ADAP: case ERROR_NETNAME_DELETED: case ERROR_BAD_DEV_TYPE:
732 case ERROR_NETWORK_ACCESS_DENIED: case ERROR_BAD_NET_NAME: case ERROR_TOO_MANY_SESS: case ERROR_REQ_NOT_ACCEP:
733 case ERROR_INVALID_PASSWORD: case ERROR_OPEN_FAILED: case ERROR_INVALID_NAME: case ERROR_FILENAME_EXCED_RANGE:
734 case ERROR_VC_DISCONNECTED:
735 rc = ERROR_FILE_NOT_FOUND;
736 pszPath = pszNext;
737 continue;
738 }
739
740 /*
741 * Fatal error or success.
742 */
743 printf("fakeldrOpenPath: *exit* plv->lv_sfn = 0x%04x, rc = %d\n", plv->lv_sfn, rc);
744 return rc;
745 }
746 } /* for iPath */
747 }
748
749 printf("fakeldrOpenPath: *exit* plv->lv_sfn = 0x%04x, rc = %d\n", plv->lv_sfn, rc);
750
751 return rc;
752}
753
754
755/**
756 * LDRClearSem - Clears the loader semaphore.
757 * (It does some garbage collection on release.)
758 * @returns NO_ERROR on sucess.
759 * OS/2 error on failure. (ERROR_INTERRUPT?)
760 * @status completely implemented.
761 */
762ULONG LDRCALL fakeLDRClearSem(void)
763{
764 return fakeKSEMReleaseMutex(&fakeLDRSem);
765}
766
767/**
768 * KSEMReuqestMutex faker.
769 * @returns NO_ERROR
770 * @param hkmtx
771 * @param ulTimeout
772 * @status completely implemented.
773 * @remark
774 */
775ULONG KRNLCALL fakeKSEMRequestMutex(HKSEMMTX hkmtx, ULONG ulTimeout)
776{
777 unsigned short usSlot = getSlot();
778 ULONG rc = NO_ERROR;
779
780 if (memcmp(&hkmtx->debug.ksem_achSignature[0], "KSEM", 4) != 0)
781 {
782 printf("fakeKSEMQueryMutex: hkmtx = %p, invalid signature (%.4s)\n", hkmtx, hkmtx->debug.ksem_achSignature);
783 return FALSE;
784 }
785
786 if (hkmtx->debug.ksem_Owner == 0)
787 {
788 hkmtx->debug.ksem_Owner = usSlot;
789 hkmtx->debug.ksem_cusNest = 1;
790 }
791 else if (hkmtx->debug.ksem_Owner == usSlot)
792 hkmtx->debug.ksem_cusNest++;
793 else
794 rc = ERROR_SEM_BUSY;
795
796 printf("fakeKSEMRequestMutex: hkmtx = %p, ulTimeout = 0x%x, owner = %d, usage count = %d, rc = %d\n",
797 hkmtx, ulTimeout, hkmtx->debug.ksem_cusNest, hkmtx->debug.ksem_Owner, ERROR_SEM_BUSY);
798
799 return rc;
800}
801
802
803/**
804 * KSEMReleaseMutex faker.
805 * @returns NO_ERROR
806 * @param hkmtx
807 * @param ulTimeout
808 * @status completely implemented.
809 * @remark
810 */
811ULONG KRNLCALL fakeKSEMReleaseMutex(HKSEMMTX hkmtx)
812{
813 unsigned int usSlot = getSlot();
814 int rc = NO_ERROR;
815
816 if (memcmp(&hkmtx->debug.ksem_achSignature[0], "KSEM", 4) != 0)
817 {
818 printf("fakeKSEMQueryMutex: hkmtx = %p, invalid signature (%.4s)\n", hkmtx, hkmtx->debug.ksem_achSignature);
819 return FALSE;
820 }
821
822 if (hkmtx->debug.ksem_Owner == usSlot)
823 {
824 if (--hkmtx->debug.ksem_cusNest == 0)
825 hkmtx->debug.ksem_Owner = 0;
826 }
827 else
828 rc = ERROR_NOT_OWNER;
829
830 printf("fakeKSEMReleaseMutex: hkmtx = %p, usage count = %d, owner = %d, rc = %d\n",
831 hkmtx, hkmtx->debug.ksem_cusNest, hkmtx->debug.ksem_Owner, rc);
832
833 return rc;
834}
835
836
837
838/**
839 * KSEMQueryMutex faker.
840 * @returns TRUE if owner or clear. Clear if *pcusNest is 0.
841 * FALSE if other owner.
842 * @param hkmtx Handle to kernel mutex.
843 * @param pcusNest Pointer to variable which is to receive the nesting count.
844 * (ie. the number of times we have taken this semaphore.)
845 * @status completely implemented.
846 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
847 */
848BOOL KRNLCALL fakeKSEMQueryMutex(HKSEMMTX hkmtx, PUSHORT pcusNest)
849{
850 unsigned int usSlot = getSlot();
851 BOOL fRc = TRUE;
852
853 if (memcmp(&hkmtx->debug.ksem_achSignature[0], "KSEM", 4) != 0)
854 {
855 printf("fakeKSEMQueryMutex: hkmtx = %p, invalid signature (%.4s)\n", hkmtx, hkmtx->debug.ksem_achSignature);
856 return FALSE;
857 }
858
859 if (hkmtx->debug.ksem_Owner == 0)
860 {
861 if (pcusNest)
862 *pcusNest = 0;
863 fRc = FALSE;
864 }
865 else
866 {
867 fRc = (hkmtx->debug.ksem_Owner == usSlot);
868 if (pcusNest)
869 *pcusNest = hkmtx->debug.ksem_cusNest;
870 }
871
872 printf("fakeKSEMQueryMutex: hkmtx = %p, usage count = %d, owner = %d, *pcusNest = %d, rc = %d\n",
873 hkmtx, hkmtx->debug.ksem_cusNest, hkmtx->debug.ksem_Owner, pcusNest ? *pcusNest : -1, fRc);
874
875 return fRc;
876}
877
878
879/**
880 * KSEMInit faker.
881 * @param pksem Pointer to the semaphore struct to initiate.
882 * @param fulType Semaphore type. (only KSEM_MUTEX is supported)
883 * @param fulFlags Semaphore flags. (not validated)
884 * @status partially implemented.
885 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
886 */
887VOID KRNLCALL fakeKSEMInit(PKSEM pksem, ULONG fulType, ULONG fulFlags)
888{
889 if (fulType != KSEM_MUTEX)
890 {
891 printf("fakeKSEMInit: Invalid fulType parameter (%d).\n", fulType);
892 return; /*ERROR_INVALID_PARAMETER;*/
893 }
894
895 memcpy(pksem->mtx.debug.ksem_achSignature, "KSEM", 4);
896 pksem->mtx.debug.ksem_bFlags = (char)fulFlags;
897 pksem->mtx.debug.ksem_bType = KSEM_MUTEX;
898 pksem->mtx.debug.ksem_cusNest = 0;
899 pksem->mtx.debug.ksem_cusPendingWriters = 0;
900 pksem->mtx.debug.ksem_Owner = 0;
901
902 printf("fakeKSEMInit: pksem=%p, fulType=%d, fulFlags=0x%x.\n", pksem, fulType, fulFlags);
903}
904
905
906/**
907 * Gets the thread slot number.
908 * @returns Thread slot number.
909 * @status completely implemented.
910 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
911 */
912unsigned short getSlot(void)
913{
914 PPIB ppib;
915 PTIB ptib;
916 BOOL f32Stack = ((int)&ppib > 0x10000);
917
918 if (!f32Stack) ThunkStack16To32();
919
920 DosGetInfoBlocks(&ptib, &ppib);
921
922 if (!f32Stack) ThunkStack32To16();
923
924 return (unsigned short)ptib->tib_ordinal;
925}
926
927
928/**
929 * Copy user memory into system memory.
930 * @returns OS/2 return code. (NO_ERROR is success)
931 * @param pv Pointer to target (system) data area.
932 * @param pvUsr Pointer to source (user) data area.
933 * @param cb Count of bytes to copy.
934 * @param fl Flags.
935 * @status Partially implemented.
936 * @remark Ignores fl. Crashes on error.
937 */
938ULONG KRNLCALL fakeTKFuBuff(PVOID pv, PVOID pvUsr, ULONG cb, ULONG fl)
939{
940 memcpy(pv, pvUsr, cb);
941
942 printf("fakeTKFuBuff: pv = %p, pvUsr = %p, cb = 0x%08x, fl = 0x%08x, rc = %d\n",
943 pv, pvUsr, cb, fl, NO_ERROR);
944
945 return NO_ERROR;
946}
947
948
949/**
950 * Copy system memory to user memory.
951 * @returns OS/2 return code. (NO_ERROR is success)
952 * @param pvUsr Pointer to target (user) data area.
953 * @param pv Pointer to source (system) data area.
954 * @param cb Count of bytes to copy.
955 * @param fl Flags.
956 * @status Partially implemented.
957 * @remark Ignores fl. Crashes on error.
958 */
959ULONG KRNLCALL fakeTKSuBuff(PVOID pvUsr, PVOID pv, ULONG cb, ULONG fl)
960{
961 memcpy(pvUsr, pv, cb);
962
963 printf("fakeTKSuBuff: pvUsr = %p, pv = %p, cb = 0x%08x, fl = 0x%08x, rc = %d\n",
964 pvUsr, pv, cb, fl, NO_ERROR);
965
966 return NO_ERROR;
967}
968
969
970/**
971 * String length. (includes NULL(s))
972 * @returns OS/2 return code. (NO_ERROR is success)
973 * ERROR_TERMINATOR_NOT_FOUND
974 * @param pcch Pointer to length variable.
975 * @param pvUsr Pointer to user data to preform string length on.
976 * @param cchMax Max string length.
977 * @param fl Flags.
978 * @param fDblNULL TRUE: Double '\0' (ie. '\0\0') terminated. Usefull for scanning environments.
979 * FALSE: Single string. (ie. one '\0').
980 * @status Partially implemented.
981 * @remark Ignores fl. Crashes on error.
982 */
983ULONG KRNLCALL fakeTKFuBufLen(PLONG pcch, PVOID pvUsr, ULONG cchMax, ULONG fl, BOOL fDblNULL)
984{
985 ULONG rc;
986 PSZ psz = pvUsr;
987
988 cchMax += (ULONG)pvUsr;
989
990 while ((ULONG)psz < cchMax)
991 {
992 if (*psz++ == '\0')
993 if (!fDblNULL || (ULONG)psz == cchMax || *psz++ != '\0')
994 break;
995 }
996
997 *pcch = (ULONG)psz - (ULONG)pvUsr;
998
999 /* Hope this is the correct definition of max length: Not inclusive. */
1000 if ((ULONG)psz == cchMax)
1001 rc = ERROR_TERMINATOR_NOT_FOUND;
1002 else
1003 rc = NO_ERROR;
1004
1005 printf("fakeTKFuBufLen: pcch = %p; *pcch = 0x%08x, pvUsr = %p, cchMax = 0x%08x, fl = 0x%08x, fDblNULL = %x, rc = %d\n",
1006 pcch, *pcch, pvUsr, cchMax, fl, fDblNULL, NO_ERROR);
1007
1008 return rc;
1009}
1010
1011
1012/**
1013 * Validates an hMTE and gets the MTE pointer - FAKE.
1014 * @returns Pointer to MTE on success.
1015 * NULL on error.
1016 * @param hMTE MTE handle.
1017 * @remark If you wan't to this faster:
1018 * Use the hMTE as a HOB and get the HOB address (by using VMGetHandleInfo).
1019 * @status stub.
1020 */
1021PMTE LDRCALL fakeldrValidateMteHandle(HMTE hMTE)
1022{
1023 DUMMY();
1024
1025 printf("fakeldrValidateMteHandle: hMTE = 0x%04x, pMTE (rc) = %p\n",
1026 hMTE, NULL);
1027
1028 return NULL;
1029}
1030
1031
1032/**
1033 * C worker function for fakeg_tkExecPgm. This is called by fakeg_tkExecPgm (fakea.asm).
1034 * @returns OS/2 return code.
1035 * @param execFlag Exec flag (DosExecPgm execFlag).
1036 * @param pArg Pointer to arguments. (NULL allowed)
1037 * @param pEnv Pointer to environment. (NULL allowed)
1038 * @param pszFilename Pointer to filename.
1039 * @sketch
1040 * @status
1041 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1042 * @remark
1043 */
1044ULONG _Optlink tkExecPgmWorker(ULONG execFlag, PSZ pArg, PSZ pEnv, PSZ pszFilename)
1045{
1046 APIRET rc;
1047 ldrrei_t rei;
1048
1049 printf("tkExecPgmWorker: execFlag = %d, pArg = %p, pEnv = %p, pszFilename = %s\n", execFlag, pArg, pEnv, pszFilename);
1050
1051 /*
1052 * Take loader semaphore.
1053 */
1054 rc = KSEMRequestMutex(&fakeLDRSem, KSEM_INDEFINITE_WAIT);
1055 if (rc != NO_ERROR)
1056 {
1057 return rc;
1058 }
1059
1060 /*
1061 * Simulate loading.
1062 */
1063 rc = fakeLDRLoadExe(pszFilename, SSToDS(&rei));
1064
1065 NOREF(pArg);
1066 NOREF(pEnv);
1067 NOREF(execFlag);
1068
1069 return rc;
1070}
1071
1072
1073/**
1074 * Fake implementation of LDRLoadExe.
1075 * Not currently overriden, but used by tkExecPgmWorker to load executables.
1076 * @returns OS/2 return code.
1077 * @param pszFilename Name of executable image to load.
1078 * @param pEI It seems this is a pointer to a ldrrei_s struct.
1079 * (currently ignored)
1080 * @sketch
1081 * @status
1082 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1083 * @remark
1084 */
1085ULONG LDRCALL fakeLDRLoadExe(PSZ pszFilename, ldrrei_t *pEI)
1086{
1087 APIRET rc;
1088 int cchFilename = strlen(pszFilename);
1089
1090 printf("fakeLDRLoadExe: *entry* pszFilename = %s, pEI = %p\n",
1091 pszFilename, pEI);
1092
1093 rc = fakeldrGetModule(pszFilename, (cchFilename << 16) | (LVTYPE_EXE << 8) | CLASS_PROGRAM);
1094
1095 printf("fakeLDRLoadExe: *exit* pszFilename = %s, pEI = %p, rc = %d\n",
1096 pszFilename, pEI, rc);
1097
1098 return rc;
1099}
1100
1101
1102
1103/**
1104 * Fake implementeation of ldrGetModule.
1105 * Not currently overriden, but used by fakeLDRLoadExe to load executables.
1106 * @returns OS/2 return code.
1107 * @param pszFilename Name of executable image to load.
1108 * @param ul low 8 bits: Module CLASS_*.
1109 * high 8 bits: Executable type LVTYPE_* ?
1110 * high 16 bits: Filename length.
1111 * @sketch
1112 * OS/2 kernel seems to do:
1113 * Call Sec32GetModule
1114 * Call ldrGetMte which does the necessary loading / attaching.
1115 * Call ldrLoadImports for all imported DLLs. (and the exe?)
1116 * Call ldrProcessObjects for LX and ldrPreloadLDT for NE imported DLLs. (and the exe?)
1117 * Call ldrProcessImports.
1118 *
1119 * We do:
1120 * Call fakeldrGetMte.
1121 * Call fakeldrLoadImports.
1122 *
1123 * @status
1124 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1125 * @remark
1126 */
1127ULONG LDRCALL fakeldrGetModule(PSZ pszFilename, ULONG ul)
1128{
1129 APIRET rc;
1130 PMTE pmte = NULL;
1131
1132 printf("fakeldrGetModule: *entry* pszFilename = %s, ul = 0x%08x\n",
1133 pszFilename, ul);
1134
1135 rc = fakeldrGetMte(pszFilename, (USHORT)(ul >> 16), (UCHAR)((ul & 0xff00) >> 8), (UCHAR)(ul & 0x00ff), SSToDS(&pmte));
1136 if (rc == NO_ERROR)
1137 {
1138 rc = fakeldrLoadImports(pmte);
1139 }
1140
1141 printf("fakeldrGetModule: *exit* pszFilename = %s, ul = 0x%08x, rc = %d\n",
1142 pszFilename, ul, rc);
1143
1144 return rc;
1145}
1146
1147
1148/**
1149 *
1150 * @returns
1151 * @param
1152 * @equiv
1153 * @time
1154 * @sketch
1155 * OS/2 kernel seems to do:
1156 * IF not device driver THEN
1157 * Uppercase the name.
1158 * Call ldrFindModule to try find the module within currenly loaded modules.
1159 * ENDIF
1160 *
1161 * tryagain:
1162 * IF found THEN
1163 * Set MTEGETMTEDONE flag in mte_flags2.
1164 * Call ldrChkLoadType to ensure correct load type.
1165 * IF attached or special modules (DOSMOD, VDDMOD, FSHMOD or MVDMMOD)
1166 * IF miniIFS and !FSHMOD THEN Fail with rc=ERROR_INVALID_NAME
1167 * return successfully.
1168 * ENDIF
1169 * lv_sfn <- mte_sfn
1170 * Set the USED flag in mte_flags1
1171 * Set the MTELOADORATTACH flag in mte_flags2
1172 * Some processing of packed segments???? Dll init flags???
1173 * ELSE *not found*
1174 * IF class is CLASS_SPECIFIC AND ldrCheckGlobal returned TRUE THEN
1175 * * this is because some specific modules is promoted to global
1176 * * modules for some reasons I haven't ivestigated. (ldrPrmoteMTE)
1177 * tryagain.
1178 * ENDIF
1179 * Set some flag to false.
1180 * Calls to ldrOpenNewExe to load the exectuble from disk.
1181 * IF this failes THEN fail.
1182 * IF class is CLASS_GLOBAL and module is loaded as specific
1183 * (ldrCheckSpecific returns TRUE) THEN
1184 * Close and retry with the mte returned ldrCheckSpecific
1185 * tryagain.
1186 * ENDIF
1187 * Sets some local variable to point at pheaderbuf, where ldrOpenNewExe
1188 * has put the executable header.
1189 * Call ldrCheckLoadType and fail if this failes.
1190 * Call ldrCreateMte and fail if this failes.
1191 * Set some local variables to lv_pmte and lv_pmte->mte_swapmte.
1192 * Set the MTELOADORATTACH and MTEGETMTEDONE flags.
1193 * Call ldrInvTgtErrTxt.
1194 * IF DDInitTime AND DEVDRVMOD OR FSDMOD THEN
1195 * ptda_module of current PTDA to the mtehandle of the module.
1196 * ENDIF
1197 * IF DOSCALL1 (checks name) THEN
1198 * Set DOSLIB flag of mte_flags1.
1199 * Set global pmteDoscall1 to point to the mte.
1200 * Set global hmteDoscall1 to the handle of the mte.
1201 * ENDIF
1202 * ENDIF
1203 * IF VDDMOD THEN
1204 * call VDMMLoadingVDD with the mte handle.
1205 * ENDIF
1206 * IF NE executable THEN
1207 * Call ldrAllocSegments
1208 * ELSE
1209 * Call ldrAllocObjects
1210 * ENDIF
1211 * IF failed THEN fail.
1212 * IF LVTYPE_EXE THEN
1213 * Set the ptda_module of the ExecChild PTDA to mtehandle.
1214 * IF MTELONGNAMES THEN
1215 * Set ptda_NewFiles to something.
1216 * ENDIF
1217 * Increment usage count, ie. mte_usecnt-
1218 * ELSE IF LVTYPE_DLL AND !somelocalflag AND NOINTERNFIXUPS THEN
1219 * Remove Internal fixups?
1220 * (Calls ldrIsInternalFixup and VMReallocKHB during this processing.)
1221 * ENDIF
1222 * Clears the MTEPROCESSED flag of mte_flags1.
1223 * Sets the return mte pointer. (ppmte)
1224 * return successfully.
1225 *
1226 * We do:
1227 * Uppercase the string. (do we have to switch stack?)
1228 * Call fakeldrOpenNewExe to do it's work.
1229 * Call fakeldrCreateMte to create a fake mte.
1230 * return.
1231 *
1232 * @status
1233 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1234 * @remark
1235 */
1236ULONG LDRCALL fakeldrGetMte(PCHAR pachFilename, USHORT cchFilename, UCHAR fchType, UCHAR fchClass, PPMTE ppmte)
1237{
1238 ldrlv_t lv;
1239 APIRET rc;
1240
1241 printf("fakeldrGetMte: *entry* pachFilename = %.*s, cchFilename = %#02x, fchType %#2x, fchClass = %#2x, ppmte = %p\n",
1242 cchFilename, pachFilename, cchFilename, fchType, fchClass, ppmte);
1243
1244 /*
1245 * Initiate the local variables.
1246 */
1247 memset(SSToDS(&lv), 0, sizeof(lv));
1248 lv.lv_sfn = (USHORT)-1;
1249 lv.lv_type = fchType;
1250 lv.lv_class = fchClass;
1251
1252 /*
1253 * Uppercase the string.
1254 */
1255 fakeldrUCaseString(pachFilename, cchFilename);
1256
1257 /*
1258 * Open the new executable.
1259 */
1260 rc = fakeldrOpenNewExe(pachFilename, cchFilename, SSToDS(&lv), NULL);
1261 if (rc != NO_ERROR)
1262 {
1263 fakeldrClose(lv.lv_sfn);
1264 printf("fakeldrGetMte: *exit* pachFilename = %.*s, ppmte = %p; *ppmte = %p, rc = %d\n",
1265 cchFilename, pachFilename, ppmte, *ppmte, rc);
1266 return rc;
1267 }
1268
1269 /*
1270 * Create MTE for the opened file.
1271 */
1272 rc = fakeldrCreateMte(pheaderbuf, SSToDS(&lv));
1273 if (rc == NO_ERROR)
1274 {
1275 /*
1276 * Set some flags... More?
1277 */
1278 lv.lv_pmte->mte_flags2 |= MTEGETMTEDONE | MTELOADORATTACH;
1279 *ppmte = lv.lv_pmte;
1280 }
1281
1282 printf("fakeldrGetMte: *exit* pachFilename = %.*s, ppmte = %p; *ppmte = %p, rc = %d\n",
1283 cchFilename, pachFilename, ppmte, *ppmte, rc);
1284
1285 return rc;
1286}
1287
1288
1289
1290/**
1291 * Opens an executable module.
1292 * @returns OS2 error code.
1293 * @param pachFilename Filename of the executable module to open.
1294 * @param cchFilename Filename length.
1295 * @param plv Pointer to local variables.
1296 * @param pus Pointer to some flags (LDRQAppType flags?!).
1297 * @sketch
1298 * OS/2 kernel seems to do:
1299 * Call ldrOpenPath to open the file.
1300 * IF this fail THEN
1301 * Set lv_sfn to -1 and return errorcode.
1302 * ENDIF
1303 * Set local variable to pheaderbuf.
1304 * IF pus THEN set *pus to 1
1305 * Call ldrRead to read the MZ header.
1306 * Fail if this failed. (Don't close file caller does that.)
1307 * IF LXMAGIC of NEMAGIC found THEN
1308 * lv_new_exe_off <- 0;
1309 * ELSE
1310 * IF !EMAGIC or 'OZ' THEN
1311 * Fail with rc=ERROR_INVALID_EXE_SIGNATURE.
1312 * ENDIF
1313 * IF pus THEN set *pus to 2.
1314 * lv_new_exe_off <- e_lfanew.
1315 * ENDIF
1316 * Call ldrRead to read LX/NE header at lv_new_exe_off.
1317 * Fail if this failed.
1318 * IF NOT LXMAGIC OR NEMAGIC THEN
1319 * IF LEMAGIC AND pus THEN Set *pus to 0.
1320 * IF PEMAGIC and pus THEN Set *pus to 3.
1321 * Fail with rc=ERROR_INVALID_EXE_SIGNATURE.
1322 * ENDIF
1323 * IF pus THEN Set *pus to 0.
1324 * IF invalid LX exeheader THEN
1325 * Fail with rc=ERROR_INVALID_EXE_SIGNATURE.
1326 * ENDIF
1327 * IF NEMAGIC THEN
1328 * Call ldrExpandHeader
1329 * ELSE
1330 * Set the MTELONGNAMES flag in e32_mflags.
1331 * ENDIF
1332 * IF LDRINVALID (in e32_mflags) THEN
1333 * Fail with rc=ERROR_EXE_MARKED_INVALID.
1334 * ENDIF
1335 * Clear some e32_mflags, MTE_MEDIAFIXED, MTEMEDIACONTIG and MTEMEDIA16M.
1336 * Or in flags set by ldrOpenPath into e32_mflags. (media type flags?!)
1337 * Call ldrMungeFlags
1338 * return retur code from ldrMungeFlags.
1339 *
1340 * We do:
1341 * Call fakeldrOpenPath to open the file.
1342 * IF this fail THEN
1343 * Set lv_sfn to -1 and return errorcode.
1344 * ENDIF
1345 * IF pus THEN set *pus to 1
1346 * Call ldrRead to read the MZ header.
1347 * Fail if this failed. (Don't close file caller does that.)
1348 * If MZ header Then
1349 * Set lv_new_exe_off to e_lfanew.
1350 * else
1351 * Set lv_new_exe_off to 0.
1352 * Call ldrRead to read the LX header.
1353 * Fail if this failed. (Don't close file caller does that.)
1354 * If Not LX signature Then
1355 * Fail.
1356 * return successfully.
1357 *
1358 * @status
1359 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1360 * @remark
1361 */
1362ULONG LDRCALL fakeldrOpenNewExe(PCHAR pachFilename, USHORT cchFilename, ldrlv_t *plv, PUSHORT pus)
1363{
1364 APIRET rc;
1365 ULONG ful;
1366
1367 printf("fakeldrOpenNewExe: *entry* pachFilename = %.*s, cchFilename = %#2, plv = %p, pus = %p\n",
1368 cchFilename, pachFilename, cchFilename, plv, pus);
1369
1370 rc = fakeldrOpenPath(pachFilename, cchFilename, plv, SSToDS(&ful));
1371 if (rc != NO_ERROR)
1372 {
1373 plv->lv_sfn = 0xffff;
1374 printf("fakeldrOpenNewExe: *exit* pachFilename = %.*s, plv->lv_sfn = %#4x, rc = %d\n",
1375 cchFilename, pachFilename, plv->lv_sfn, rc);
1376 return rc;
1377 }
1378 if (pus) *pus = 1;
1379
1380 memset(pheaderbuf, 0, sizeof(struct exe_hdr)); //zero it just in case....
1381 rc = fakeldrRead(plv->lv_sfn, 0, pheaderbuf, 0, sizeof(struct exe_hdr), NULL);
1382 if (rc != NO_ERROR)
1383 {
1384 plv->lv_sfn = 0xffff;
1385 printf("fakeldrOpenNewExe: *exit* pachFilename = %.*s, plv->lv_sfn = %#4x, rc = %d\n",
1386 cchFilename, pachFilename, plv->lv_sfn, rc);
1387 return rc;
1388 }
1389
1390 if (*(PUSHORT)pheaderbuf == EMAGIC)
1391 plv->lv_new_exe_off = ((struct exe_hdr *)pheaderbuf)->e_lfanew;
1392 else
1393 plv->lv_new_exe_off = 0;
1394
1395 memset(pheaderbuf, 0, sizeof(struct e32_exe)); //zero it just in case....
1396 rc = fakeldrRead(plv->lv_sfn, plv->lv_new_exe_off, pheaderbuf, 0, sizeof(struct e32_exe), NULL);
1397 if (rc != NO_ERROR)
1398 {
1399 plv->lv_sfn = 0xffff;
1400 printf("fakeldrOpenNewExe: *exit* pachFilename = %.*s, plv->lv_sfn = %#4x, rc = %d\n",
1401 cchFilename, pachFilename, plv->lv_sfn, rc);
1402 return rc;
1403 }
1404
1405 if (*(PUSHORT)pheaderbuf != E32MAGIC)
1406 {
1407 plv->lv_sfn = 0xffff;
1408 rc = ERROR_INVALID_EXE_SIGNATURE;
1409 printf("fakeldrOpenNewExe: *exit* pachFilename = %.*s, plv->lv_sfn = %#4x, rc = %d\n",
1410 cchFilename, pachFilename, plv->lv_sfn, rc);
1411 return rc;
1412 }
1413
1414 printf("fakeldrOpenNewExe: *exit* pachFilename = %.*s, plv->lv_sfn = %#4x, rc = %d\n",
1415 cchFilename, pachFilename, plv->lv_sfn, rc);
1416
1417 return NO_ERROR;
1418}
1419
1420
1421/**
1422 * Fake ldrCreateMte implementation.
1423 * @returns
1424 * @param pe32 Pointer to the LX/NE header we've just read.
1425 * @param plv Pointer to local variables.
1426 * @sketch !This does a lot of thing!
1427 *
1428 * OS/2 Kernel seems to do:
1429 * Allocate a kernel heap block for the MTE
1430 *
1431 *
1432 *
1433 *
1434 *
1435 *
1436 *
1437 *
1438 *
1439 *
1440 * We do:
1441 *
1442 *
1443 * @status
1444 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1445 * @remark
1446 */
1447ULONG LDRCALL fakeldrCreateMte(struct e32_exe *pe32, ldrlv_t *plv)
1448{
1449 ULONG rc;
1450 PMTE pMte;
1451 PSMTE pSMte;
1452 PCHAR pch;
1453
1454 printf("fakeldrCreateMte: *entry* pe32 = %p, plv = %d\n",
1455 pe32, plv);
1456
1457 /*
1458 * Allocate mte and smte.
1459 * The MTE has an array of mte pointers at the end for imported modules + 1.
1460 * The SMTE has the fullpath filename, loader section and fixup section.
1461 */
1462 pMte = malloc(sizeof(MTE) + sizeof(PMTE) + sizeof(PMTE)*pe32->e32_impmodcnt);
1463 if (pMte == NULL)
1464 {
1465 rc = ERROR_NOT_ENOUGH_MEMORY;
1466 goto createmte_exit;
1467 }
1468
1469 plv->lv_csmte = sizeof(SMTE) + 260 + pe32->e32_ldrsize + pe32->e32_fixupsize;
1470 pSMte = malloc(plv->lv_csmte);
1471 if (pSMte == NULL)
1472 {
1473 rc = ERROR_NOT_ENOUGH_MEMORY;
1474 goto createmte_exit;
1475 }
1476 pch = (PCHAR)(PVOID)pSMte + sizeof(SMTE) + 260;
1477
1478
1479 /*
1480 * Initialize the MTE.
1481 */
1482 pMte->mte_flags2 = MTEFORMATLX;
1483 pMte->mte_handle = 20;
1484 pMte->mte_swapmte = pSMte;
1485 pMte->mte_link = NULL;
1486 pMte->mte_flags1 = pe32->e32_mflags;
1487 pMte->mte_impmodcnt = pe32->e32_impmodcnt;
1488 pMte->mte_sfn = plv->lv_sfn;
1489 pMte->mte_usecnt = 0;
1490 pMte->mte_modname[0]= '\0';
1491
1492 /*
1493 * Initialize the SMTE.
1494 */
1495 pSMte->smte_mpages = pe32->e32_mpages;
1496 /*- magic,border,worder,level,cpu,os,ver,mflags */
1497 pSMte->smte_mpages = pe32->e32_mpages; /* 00 Module # pages */
1498 pSMte->smte_startobj = pe32->e32_startobj; /* 04 Object # for instruction */
1499 pSMte->smte_eip = pe32->e32_eip; /* 08 Extended instruction pointer */
1500 pSMte->smte_stackobj = pe32->e32_stackobj; /* 0c Object # for stack pointer */
1501 pSMte->smte_esp = pe32->e32_esp; /* 10 Extended stack pointer */
1502 /*- pagesize*/
1503 pSMte->smte_pageshift = pe32->e32_pageshift; /* 14 Page alignment shift in .EXE */
1504 pSMte->smte_fixupsize = pe32->e32_fixupsize; /* 18 Fixup section size */
1505 /*- fixupsum,ldrsize,ldrsum*/
1506 pSMte->smte_objtab = (POTE)pe32->e32_objtab; /* 1c Object table offset - POINTER */
1507 pSMte->smte_objcnt = pe32->e32_objcnt; /* 20 Number of objects in module */
1508 pSMte->smte_objmap = pe32->e32_objmap; /* 24 Object page map offset - POINTER */
1509 pSMte->smte_itermap = pe32->e32_itermap; /* 28 Object iterated data map offset */
1510 pSMte->smte_rsrctab = pe32->e32_rsrctab; /* 2c Offset of Resource Table */
1511 pSMte->smte_rsrccnt = pe32->e32_rsrccnt; /* 30 Number of resource entries */
1512 pSMte->smte_restab = pe32->e32_restab; /* 34 Offset of resident name table - POINTER */
1513 pSMte->smte_enttab = pe32->e32_enttab; /* 38 Offset of Entry Table - POINTER */
1514 pSMte->smte_fpagetab = pe32->e32_fpagetab; /* 3c Offset of Fixup Page Table - POINTER */
1515 pSMte->smte_frectab = pe32->e32_frectab; /* 40 Offset of Fixup Record Table - POINTER */
1516 pSMte->smte_impmod = pe32->e32_impmod; /* 44 Offset of Import Module Name Table - POINTER */
1517 /*- impmodcnt*/
1518 pSMte->smte_impproc = pe32->e32_impproc; /* 48 Offset of Imp Procedure Name Tab - POINTER */
1519 /*- pagesum*/
1520 pSMte->smte_datapage = pe32->e32_datapage; /* 4c Offset of Enumerated Data Pages */
1521 /*- preload*/
1522 pSMte->smte_nrestab = pe32->e32_nrestab; /* 50 Offset of Non-resident Names Table */
1523 pSMte->smte_cbnrestab = pe32->e32_cbnrestab; /* 54 Size of Non-resident Name Table */
1524 /*- nressum*/
1525 pSMte->smte_autods = pe32->e32_autodata; /* 58 Object # for automatic data object */
1526 pSMte->smte_debuginfo = pe32->e32_debuginfo; /* 5c Offset of the debugging info */
1527 pSMte->smte_debuglen = pe32->e32_debuglen; /* 60 The len of the debug info in */
1528 /*- instpreload,instdemand*/
1529 pSMte->smte_heapsize = pe32->e32_heapsize; /* 64 use for converted 16-bit modules */
1530 /*- res3*/
1531 /* extra */
1532 pSMte->smte_path = 0; /* 68 full pathname - POINTER */
1533 pSMte->smte_semcount = 0; /* 6c Count of threads waiting on MTE semaphore. 0 => semaphore is free */
1534 pSMte->smte_semowner = 0; /* 6e Slot number of the owner of MTE semahore */
1535 pSMte->smte_pfilecache = 0; /* 70 Pointer to file cache for Dos32CacheModule */
1536 pSMte->smte_stacksize = 0; /* 74 Thread 1 Stack size from the exe header */
1537 pSMte->smte_alignshift = 0; /* 78 use for converted 16-bit modules */
1538 pSMte->smte_NEexpver = 0; /* 7a expver from NE header */
1539 pSMte->smte_pathlen = 0; /* 7c length of full pathname */
1540 pSMte->smte_NEexetype = 0; /* 7e exetype from NE header */
1541 pSMte->smte_csegpack = 0; /* 80 count of segs to pack */
1542
1543 /*
1544 * Copy filename (from where?)
1545 */
1546 pSMte->smte_path = (PCHAR)(PVOID)pSMte + sizeof(SMTE);
1547 pSMte->smte_pathlen = 0;
1548 memcpy(pSMte->smte_path, "", pSMte->smte_pathlen);
1549
1550
1551 /*
1552 * Read loader and fixup sections.
1553 */
1554 rc = fakeldrRead(plv->lv_sfn,
1555 (ULONG)pSMte->smte_objtab + plv->lv_new_exe_off,
1556 pch,
1557 0,
1558 pe32->e32_ldrsize + pe32->e32_fixupsize,
1559 NULL);
1560 if (rc)
1561 {
1562 goto createmte_exit;
1563 }
1564
1565 /*
1566 * Set pointers.
1567 */
1568 pSMte->smte_objtab = (POTE)(PVOID)pch;
1569 rc = fakeldrMTEValidatePtrs(pSMte,
1570 (ULONG)pch + plv->lv_csmte,
1571 (ULONG)pch - (ULONG)pe32->e32_objtab);
1572 if (rc)
1573 {
1574 goto createmte_exit;
1575 }
1576
1577 /*
1578 * Set mte pointer in plv.
1579 * Set hobmte in plv.
1580 */
1581 plv->lv_pmte = pMte;
1582 plv->lv_hobmte = pMte->mte_handle;
1583
1584 /*
1585 * Fix flags...
1586 */
1587 pMte->mte_flags1 |= plv->lv_class;
1588
1589createmte_exit:
1590 printf("fakeldrCreateMte: *exit* pe32 = %p, plv = %d, rc = %d\n",
1591 pe32, plv, rc);
1592
1593 return rc;
1594}
1595
1596
1597
1598/**
1599 * Fake ldrLoadImports - loads the import modules for the given module (pmte).
1600 * @returns OS2 error code.
1601 * @param pmte Pointer to mte to load imports for.
1602 * @sketch
1603 * OS/2 kernel seems to do:
1604 * Loop thru the importe module table (reverse order for NE files)
1605 * IF VDD module THEN
1606 * Uppercase the name.
1607 * try find it using ldrFindModule
1608 * fail if error, not found, not VDDMOD/MVDMMOD.
1609 * Add to array of imported module.
1610 * ENDIF
1611 * IF Not found OR !MTEGETMTEDONE THEN
1612 * call ldrGetMte to load the module (class global).
1613 * fail if error.
1614 * set MTEGETMTEDONE
1615 * Add to array of imported module.
1616 * ENDIF
1617 * IF DOSMOD and !ldrMiniFileIOFlag THEN
1618 * Replace module pointer with doscall1 pmte.
1619 * ENDIF
1620 * ENDLOOP
1621 *
1622 * We do:
1623 * Parameter validation.
1624 * Loop thru the imported module table issuing fakeldrGetMte on each entry.
1625 * 'DOSCALLS' is ignored.
1626 *
1627 * @status
1628 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1629 * @remark
1630 */
1631ULONG LDRCALL fakeldrLoadImports(PMTE pmte)
1632{
1633 int i; /* Module index. */
1634 PSZ psz; /* Module name pointer. (really pointer to pascal strings...) */
1635 PPMTE papmte; /* Pointer to array of PMTEs for imported modules. */
1636 APIRET rc;
1637
1638 printf("fakeldrLoadImport: *entry* pmte = %p, pmte->mte_impmodcnt = %d\n",
1639 pmte, pmte->mte_impmodcnt);
1640
1641 /*
1642 * Parameter validation.
1643 */
1644 if (pmte == NULL)
1645 {
1646 kprintf(("fakeldrLoadImports: !ASSERTION! pmte == NULL\n"));
1647 return ERROR_INVALID_PARAMETER;
1648 }
1649 if (pmte->mte_swapmte == NULL)
1650 {
1651 kprintf(("fakeldrLoadImports: !ASSERTION! pmte->mte_swapmte == NULL\n"));
1652 return ERROR_INVALID_PARAMETER;
1653 }
1654
1655 /*
1656 * Any imported modules?
1657 */
1658 if (pmte->mte_impmodcnt == 0)
1659 {
1660 printf("fakeldrLoadImport: *exit* pmte = %p, rc = %d\n",
1661 pmte, rc);
1662 return NO_ERROR;
1663 }
1664
1665 /* We have reserved space for imported module pointers after the mte. */
1666 papmte = (PPMTE)((unsigned)pmte + sizeof(MTE));
1667
1668 /*
1669 * Process the imported module table.
1670 */
1671 for (i = 0, rc = NO_ERROR, psz = (PSZ)pmte->mte_swapmte->smte_impmod;
1672 i < pmte->mte_impmodcnt && rc == NO_ERROR;
1673 i++, psz += 1 + *psz)
1674 {
1675 if (*psz == 8 && !strnicmp(psz+1, "DOSCALLS", 8))
1676 continue;
1677
1678 rc = fakeldrGetMte(psz + 1, *psz, LVTYPE_DLL, CLASS_GLOBAL, &papmte[i]);
1679 }
1680
1681 printf("fakeldrLoadImport: *exit* pmte = %p, rc = %d\n",
1682 pmte, rc);
1683
1684 return rc;
1685}
1686
1687
1688
1689/**
1690 * Uppercases the string.
1691 * @param pachString String to uppercase.
1692 * @param cchString Length of string.
1693 * @sketch Loop thru the string converting all english letters to uppercase.
1694 * @status partially implemented.
1695 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1696 * @remark This is probably written in assembly and does DBCS checks...
1697 */
1698VOID LDRCALL fakeldrUCaseString(PCHAR pachString, USHORT cchString)
1699{
1700 printf("fakeldrUCaseString: pachString = %.*s, cchString = %#8x\n",
1701 cchString, pachString, cchString);
1702
1703 while (cchString-- != 0)
1704 {
1705 if (*pachString >= 'a' && *pachString <= 'z')
1706 *pachString -= ('a' - 'A');
1707 pachString++;
1708 }
1709}
1710
1711
1712
1713
1714/**
1715 * Checks and updates the members of the swap-mte which is to be
1716 * pointers into the loader/fixup section. An array, validatetbl, contains
1717 * the offsets of the smte pointers.
1718 *
1719 * @returns NO_ERROR on success.
1720 * ERROR_BAD_EXE_FORMAT on error.
1721 * @param psmte
1722 * @param ulMaxAddr Maximum (exclusive) address.
1723 * @param off Offset delta to add to the pointer members (which
1724 * are all offsets relative to the start of the new
1725 * header) to make them pointers.
1726 * @sketch
1727 * Loop thru the validatetbl and update each field (which isn't null) by adding
1728 * the off value, and validate that the pointer is ok.
1729 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1730 * @remark
1731 */
1732ULONG LDRCALL fakeldrMTEValidatePtrs(PSMTE psmte, ULONG ulMaxAddr, ULONG off)
1733{
1734 int i;
1735
1736 printf("fakeldrMTEValidatePtrs: *entry* psmte = %p, ulMaxAddr = %p, off = %p\n",
1737 psmte, ulMaxAddr, off);
1738
1739 for (i = 0; validatetbl[i] != 0xDEAD; i++)
1740 {
1741 PULONG pul = (PULONG)(PVOID)((PCHAR)(PVOID)psmte + validatetbl[i]);
1742 if (*pul != 0UL)
1743 {
1744 *pul += off;
1745 if (*pul >= ulMaxAddr)
1746 {
1747 printf("fakeldrMTEValidatePtrs: *exit* psmte = %p, ulMaxAddr = %p, off = %p, rc = %d\n",
1748 psmte, ulMaxAddr, off, ERROR_BAD_EXE_FORMAT);
1749 return ERROR_BAD_EXE_FORMAT;
1750 }
1751 }
1752 }
1753
1754 printf("fakeldrMTEValidatePtrs: *exit* psmte = %p, ulMaxAddr = %p, off = %p, rc = %d\n",
1755 psmte, ulMaxAddr, off, NO_ERROR);
1756 return NO_ERROR;
1757}
1758
1759
1760PMTE KRNLCALL fakeldrASMpMTEFromHandle(HMTE hMTE)
1761{
1762 PMTE pMte = (PMTE)hMTE;
1763
1764 pMte += 10; //just do something!
1765
1766 return NULL;
1767}
1768
1769ULONG LDRCALL fakeldrFindModule(PCHAR pachFilename, USHORT cchFilename, USHORT usClass, PPMTE ppMTE)
1770{
1771 APIRET rc = NO_ERROR;
1772 usClass = usClass;
1773 cchFilename = cchFilename;
1774 pachFilename = pachFilename;
1775 *ppMTE = NULL;
1776 return rc;
1777}
1778
1779
1780/**
1781 * Gets the path (name with fully qualified path) from a SFN.
1782 * @returns Pointer to the path of hFile.
1783 * @param hFile SFN filehandle.
1784 */
1785PSZ SECCALL fakeSecPathFromSFN(SFN hFile)
1786{
1787 APIRET rc;
1788 BOOL f32Stack = ((int)&hFile > 0x10000);
1789
1790 if (!f32Stack) ThunkStack16To32();
1791
1792 rc = ERROR_NOT_SUPPORTED;
1793
1794 if (!f32Stack) ThunkStack32To16();
1795
1796 printf("fakeSecPathFromSFN: - not implemented - hFile = 0x%04x, rc = %d\n", hFile, rc);
1797
1798 return rc;
1799}
1800
Note: See TracBrowser for help on using the repository browser.