Changeset 4164 for trunk/src/win32k/ldr/myldrOpen.cpp
- Timestamp:
- Sep 2, 2000, 11:08:23 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/win32k/ldr/myldrOpen.cpp
r2838 r4164 1 /* $Id: myldrOpen.cpp,v 1.1 0 2000-02-21 09:24:01bird Exp $1 /* $Id: myldrOpen.cpp,v 1.11 2000-09-02 21:08:09 bird Exp $ 2 2 * 3 3 * myldrOpen - ldrOpen. 4 4 * 5 * Copyright (c) 1998- 1999knut st. osmundsen5 * Copyright (c) 1998-2000 knut st. osmundsen 6 6 * 7 7 * Project Odin Software License can be found in LICENSE.TXT … … 17 17 18 18 #define INCL_OS2KRNL_IO 19 #define INCL_OS2KRNL_TCB 20 #define INCL_OS2KRNL_SEM 21 #define INCL_OS2KRNL_SEC 19 22 20 23 /******************************************************************************* … … 23 26 #include <os2.h> 24 27 28 #include "devSegDf.h" /* Win32k segment definitions. */ 25 29 #include "rmalloc.h" 26 30 #include "malloc.h" … … 28 32 #include <stdlib.h> 29 33 #include <string.h> 34 #include <stdarg.h> 30 35 31 36 #include "log.h" 37 #include "avl.h" 38 #include "options.h" 32 39 #include <peexe.h> 33 40 #include <exe386.h> 41 #include "elf.h" 34 42 #include "OS2Krnl.h" 35 43 #include "dev32.h" 44 #include "ldr.h" 45 #include "ldrCalls.h" 36 46 #include "ModuleBase.h" 37 47 #include "pe2lx.h" 38 #include "elf.h"39 #include "avl.h"40 #include "ldr.h"41 #include "ldrCalls.h"42 #include "options.h"43 48 #include "myExecPgm.h" 44 45 /******************************************************************************* 46 * Global Variables * 47 *******************************************************************************/ 48 extern BOOL fQAppType; /* From LDRQAppType */ 49 #include "env.h" 50 #include "vprintf.h" /* Make 100% sure we have va_start. */ 51 52 49 53 50 54 /******************************************************************************* 51 55 * Internal Functions * 52 56 *******************************************************************************/ 53 static unsigned getArgsLength(const char *pachArgs); 57 /* static */ APIRET AddArgsToFront(int cArgs, ...); 58 /* static */ APIRET SetExecName(const char *pszExeName); 59 /* static */ APIRET OpenPATH(PSFN phFile, char *pszFilename, PULONG pfl); 54 60 55 61 … … 59 65 * @param phFile Pointer to file handler. Holds filehandle on output. 60 66 * @param pszFilename Pointer to filename. 61 * @parma p aram3 Probablysome flags.67 * @parma pfl Pointer to some flags. 62 68 */ 63 ULONG LDRCALL myldrOpen(PSFN phFile, char *pszFilename, ULONG param3)69 ULONG LDRCALL myldrOpen(PSFN phFile, PSZ pszFilename, PULONG pfl) 64 70 { 65 ULONG rc; 66 67 /* 68 * Try open the file (thats why this function is called anyway) 71 static int cNesting = 0; /* This is an variable which hold the nesting */ 72 /* level of this function. This is useful */ 73 /* when we call it recurcively. */ 74 /* The maximum nesting level is currently 3. */ 75 /* When the maximum depth has been reached */ 76 /* we'll not intercept loading any longer! */ 77 ULONG rc; /* Return value. */ 78 79 /** @sketch 80 * Try open the file (that's why this function is called anyway) 69 81 */ 70 rc = ldrOpen(phFile, pszFilename, param3); 71 72 /* log sucesses */ 82 rc = ldrOpen(phFile, pszFilename, pfl); 73 83 if (rc == NO_ERROR) 74 kprintf(("ldrOpen: phFile=%#.4x, flags=%#.8x, pszFn=%s\n", *phFile, param3, pszFilename)); 75 76 /* 84 kprintf(("myldrOpen-%d: phFile=%#.4x, flags=%#.8x, pszFn=%s\n", cNesting, *phFile, pfl, pszFilename)); 85 86 87 /** @sketch 77 88 * Are we to intercept the loading? 78 * - Only if open were succesful and one of the loaders are enabled. 89 * - If open were successful. 90 * - And Not too deep nesting. 91 * - And that this isn't an unsupported load. 92 * - And one of the loaders are enabled. 79 93 */ 80 if (rc == NO_ERROR && (options.fElf || options.fPE != FLAGS_PE_NOT || options.fScript)) 81 { 82 char *pszBuffer = (char*)rmalloc(640); /* Read buffer. */ 83 PIMAGE_DOS_HEADER pMzHdr = (PIMAGE_DOS_HEADER)pszBuffer; /* Pointer to the buffer as it were a dosheader. */ 84 PIMAGE_NT_HEADERS pNtHdrs = (PIMAGE_NT_HEADERS)pszBuffer; /* Pointer to the buffer as if it were an NT header. */ 85 char *pach = pszBuffer; /* Finally an pointer to the buffer as if it were chars.. (which it is!) */ 86 PEXECPGMBUFFER pBuffer; /* Pointer to a buffer containing the programname and arguments. */ 87 /* For scripts and PE.EXE this has to be changed to have correct */ 88 /* parameters sendt in to the program. */ 89 unsigned cchRead = sizeof(IMAGE_DOS_HEADER); /* Amount of the buffer which contains valid data. */ 90 unsigned cbFile; /* Filesize (0xffffffff if call to SftFileSize failed - should _never_ happen though) */ 91 92 /* 93 * Verify that rmalloc completed successfully. 94 */ 95 if (pszBuffer == NULL) 94 if (rc == NO_ERROR 95 && cNesting < 3 96 && !isLdrStateLoadingUnsupported() 97 && isAnyLoaderEnabled() 98 ) 99 { 100 union _u_ReadBufferPointers /* Read buffer pointer(s). */ 96 101 { 97 kprintf(("ldrOpen: rmalloc(1024) failed\n")); 98 return NO_ERROR; 102 char *pach; /* Pointer to the buffer as char. */ 103 unsigned long *pul; /* Pointer to the buffer as unsigned long. */ 104 PIMAGE_DOS_HEADER pMzHdr; /* Use the buffer as a dosheader. */ 105 PIMAGE_NT_HEADERS pNtHdrs; /* Use the buffer as a NT header. */ 106 } u1; 107 unsigned cbFile; /* Filesize (0xffffffff if call to SftFileSize failed - should _never_ happen though) */ 108 unsigned cbRead; /* Amount of the buffer which contains valid data. */ 109 char * psz; /* Multipurpose string pointer no.1. */ 110 char * psz2; /* Multipurpose string pointer no.2. */ 111 char * psz3; /* Multipurpose string pointer no.3. */ 112 113 /** @sketch 114 * Allocate read buffer from resident heap. 115 * IF this fails THEN we'll simply return NO_ERROR. 116 */ 117 u1.pach = (char*)rmalloc(640); 118 if (u1.pach == NULL) 119 { 120 kprintf(("myldrOpen-%d: rmalloc(640) failed\n", cNesting)); 121 goto ret; 99 122 } 100 123 101 /* 102 * Try get the filesize 124 125 /** @sketch 126 * Increment nesting level. 127 */ 128 cNesting++; 129 130 131 /** @sketch 132 * Get the filesize. On failure filesize is set to ~0. 103 133 */ 104 134 rc = SftFileSize(*phFile, (PULONG)SSToDS(&cbFile)); 105 135 if (rc != NO_ERROR) 106 136 { 107 kprintf((" ldrOpen: SftFileSize failed with rc=%d\n", rc));137 kprintf(("myldrOpen-%d: SftFileSize failed with rc=%d\n", cNesting, rc)); 108 138 cbFile = (unsigned)~0; 109 139 } 110 140 111 /* 112 * See if this is an recognizable module format. 113 * This costs up to two disk reads! 114 */ 115 rc = ldrRead(*phFile, 0UL, pMzHdr, 0UL, cchRead, NULL); 116 if (rc == NO_ERROR) 141 142 /** @sketch 143 * Read the size of a DOS (ie. MZ) header. 144 * IF successful and more stuff in file THEN 145 * See if this is an recognizable module binary format: 146 */ 147 cbRead = min(sizeof(IMAGE_DOS_HEADER), cbFile); 148 rc = ldrRead(*phFile, 0UL, u1.pMzHdr, 0UL, cbRead, NULL); 149 if (rc == NO_ERROR && cbRead < cbFile) 117 150 { 118 /* 119 * PE header? 120 * - If DOS Magic is found AND a valid e_lfanew (offset of NE/LX/LE/PE header) is found 121 * - OR if PE siganture is found. 151 /** @sketch 152 * If LX header just give up at once. 122 153 */ 123 if ((pMzHdr->e_magic == IMAGE_DOS_SIGNATURE && 124 pMzHdr->e_lfanew > sizeof(IMAGE_DOS_HEADER) && pMzHdr->e_lfanew < 0x04000000UL) /* Larger than 64 bytes and less that 64MB. */ 125 || *(PULONG)pach == IMAGE_NT_SIGNATURE) 126 { /* 127 * MZ or PE header found 154 if (u1.pMzHdr->e_magic == E32MAGIC) 155 goto cleanup; 156 157 /** @sketch 158 * IF PE or MZ header THEN 159 */ 160 if (u1.pMzHdr->e_magic == IMAGE_DOS_SIGNATURE 161 || u1.pNtHdrs->Signature == IMAGE_NT_SIGNATURE) 162 { 163 ULONG offPe; /* Offset to PE header. */ 164 165 /** @sketch 166 * --- 167 * We now known that this is file has a MZ or a PE header. If it's 168 * a MZ header, we might end up with no "New" header or the "New" 169 * header might turn out to be a NE, LE, or LX header. I any of 170 * these non PE headers occur OS/2 will take care of it, we'll do nothing. 171 * --- 172 * IF PE loading is disable or MZ header and e_lfanew is invalid THEN 173 * return (successfully) to the caller. 174 * ENDIF 175 * (Find the offset of the PE header while testing (offPe).) 128 176 */ 129 130 /* if PE loading is diable return to the caller */131 if ( options.fPE == FLAGS_PE_NOT)177 if (isPELoaderDisabled()) 178 goto cleanup; 179 if (u1.pMzHdr->e_magic == IMAGE_DOS_SIGNATURE) 132 180 { 133 rfree(pszBuffer); 134 return NO_ERROR; 181 offPe = u1.pMzHdr->e_lfanew; 182 if (offPe < sizeof(IMAGE_DOS_HEADER) || offPe > 0x04000000UL) 183 goto cleanup; 135 184 } 136 137 /* 138 * Read the PE header if it isn't what we allready have! 185 else 186 offPe = 0; 187 188 189 /** @sketch 190 * Read the PE header. 191 * If the read failes or not PE signature, there isn't anything for us to do. 139 192 */ 140 cchRead = sizeof(IMAGE_NT_HEADERS); 141 if (*(PULONG)pach != IMAGE_NT_SIGNATURE) 142 rc = ldrRead(*phFile, pMzHdr->e_lfanew, pach, 0UL, cchRead, NULL); 143 else 144 rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL); 145 146 /* 147 * If successfully read, and a PE signature is present the continue and try load it! 148 * Else don't do anything, simply return NO_ERROR to the caller. (probably NE or LX exec) 193 rc = ldrRead(*phFile, offPe, u1.pach, 0UL, sizeof(IMAGE_NT_HEADERS), NULL); 194 if (rc != NO_ERROR || u1.pNtHdrs->Signature != IMAGE_NT_SIGNATURE) 195 goto cleanup_noerror; 196 197 198 /** @sketch 199 * PE signature found! 149 200 */ 150 if (rc == NO_ERROR && *(PULONG)pach == IMAGE_NT_SIGNATURE) 151 { /* 152 * PE signature found. 153 */ 154 kprintf(("ldrOpen: PE executable...\n")); 155 156 /* 157 * PE2LX? 158 * - When PE2LX flag is set 159 * - OR when the MIXED flag is set and the image is with the first 64MB of memory. 160 */ 161 if (options.fPE == FLAGS_PE_PE2LX 162 || (options.fPE == FLAGS_PE_MIXED 163 && !((pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL == 0UL) 164 && pNtHdrs->OptionalHeader.ImageBase >= 0x04000000UL /* 64MB */ 165 ) 201 kprintf(("myldrOpen-%d: PE executable...\n", cNesting)); 202 203 204 /** @sketch 205 * Use Pe2Lx? 206 * - When Pe2Lx flag is set 207 * - When the MIXED flag is set and the image isn't an executable 208 * above the first 64MB private limit without relocations 209 */ 210 if (isPe2LxLoaderEnabled() 211 || (isMixedPeLoaderEnabled() 212 && ((u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL) 213 || !(u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) 214 || u1.pNtHdrs->OptionalHeader.ImageBase < 0x04000000UL /* 64MB */ 166 215 ) 167 216 ) 168 { /* 169 * Pe2Lx (Ring0 of course) 170 * - Create a Pe2Lx class, 171 * - initiate it 172 * - Add the module to the module tree so we may find it later... 173 * - Set the handle state to 'our'. 174 */ 175 Pe2Lx * pPe2Lx = new Pe2Lx(*phFile); 176 if (pPe2Lx != NULL) 217 ) 218 { /** @sketch 219 * Pe2Lx (Ring0 of course) 220 * - Create a Pe2Lx class, 221 * - initiate it 222 * - Add the module to the module tree so we may find it later... 223 * - Set the (file)handle state to 'our'. 224 * - Set pExeModule to module pointer and loaderstate to our exe. 225 */ 226 Pe2Lx * pPe2Lx = new Pe2Lx(*phFile); 227 if (pPe2Lx != NULL) 228 { 229 rc = pPe2Lx->init(pszFilename); 230 if (rc == NO_ERROR) 177 231 { 178 rc = pPe2Lx->init(pszFilename); 232 kprintf(("myldrOpen-%d: Successfully init of Pe2Lx object.\n", cNesting)); 233 rc = addModule(*phFile, NULL, MOD_TYPE_PE2LX, pPe2Lx); 179 234 if (rc == NO_ERROR) 180 235 { 181 kprintf(("ldrOpen: Successfully init of Pe2Lx object.\n")); 182 rc = addModule(*phFile, NULL, MOD_TYPE_PE2LX, pPe2Lx); 183 if (rc == NO_ERROR) 184 #pragma info(notrd) 185 SetState(*phFile, HSTATE_OUR); 186 #pragma info(restore) 187 else 188 kprintf(("ldrOpen: Failed to add the module. rc=%d\n")); 236 #pragma info(notrd) 237 SetState(*phFile, HSTATE_OUR); 238 #pragma info(restore) 239 if (pPe2Lx->isExe()) 240 { 241 setLdrStateLoadingOurEXE(); 242 pExeModule = getModuleBySFN(*phFile); 243 #ifdef DEBUG 244 if (pExeModule == NULL) 245 kprintf(("myldrOpen-%d: getModuleBySFN failed when setting pExeModule! FATAL!\n", cNesting)); 246 #endif 247 } 189 248 } 190 249 else 191 kprintf(("ldrOpen: Failed to init Pe2Lx object. rc=%d\n")); 192 if (rc != NO_ERROR) 193 delete pPe2Lx; 250 kprintf(("myldrOpen-%d: Failed to add the module. rc=%d\n", cNesting)); 194 251 } 195 252 else 196 kprintf(("ldrOpen: Failed to allocate Pe2Lx object.\n")); 253 kprintf(("myldrOpen-%d: Failed to init Pe2Lx object. rc=%d\n", cNesting)); 254 if (rc != NO_ERROR) 255 delete pPe2Lx; 197 256 } 198 257 else 199 258 { 200 /* 201 * Starting of PE.EXE enable? 259 kprintf(("myldrOpen-%d: Failed to allocate Pe2Lx object.\n", cNesting)); 260 rc = ERROR_NOT_ENOUGH_MEMORY; 261 } 262 263 goto cleanup; 264 } 265 266 267 /** @sketch 268 * Using PE.EXE to start EXE? 269 * - When the file is an EXE file and PE.EXE is enabled. 270 */ 271 if ((u1.pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0UL 272 && (options.fPE == FLAGS_PE_PE || options.fPE == FLAGS_PE_MIXED) 273 && (isLdrStateExecPgm() || isLdrStateQAppType()) 274 ) 275 { 276 /** @sketch 277 * PE.EXE: 278 * Find pe.exe - look in current directory and thru the PATH. 279 * Note! We use the read buffer (u1.p*) as a storage for the 280 * pe.exe filename and path. 281 */ 282 kprintf(("myldrOpen-%d: pe.exe - opening\n", cNesting)); 283 ldrClose(*phFile); 284 strcpy(u1.pach, "PE.EXE"); 285 rc = ldrOpen(phFile, u1.pach, pfl); /* This isn't recusive! */ 286 if (rc != NO_ERROR) 287 rc = OpenPATH(phFile, u1.pach, pfl); 288 if (rc == NO_ERROR) 289 { 290 /** @sketch 291 * If we're in tkExecPgm state we'll have to shuffle the parameters 292 * and executable filename tkExecPgm were called with. 293 * If not tkExecPgm we can't do anything about parameters (and there is 294 * probably nothing to do either). 202 295 */ 203 if (options.fPE == FLAGS_PE_PE || options.fPE == FLAGS_PE_MIXED) 204 { /* 205 * pe.exe - need the path! 206 */ 207 kprintf(("ldrOpen: pe.exe - opening\n")); 208 ldrClose(*phFile); 209 rc = ldrOpen(phFile, "pe.exe", param3); /* path....! problems! */ 210 kprintf(("ldrOpen: pe.exe - open returned with rc = %d\n", rc)); 211 rfree(pszBuffer); 212 return rc; 296 kprintf(("myldrOpen-%d: pe.exe - %s\n", cNesting, u1.pach)); 297 if (isLdrStateExecPgm() && fTkExecPgm) 298 { 299 rc = AddArgsToFront(2, ldrpFileNameBuf, achTkExecPgmFilename); 300 if (rc == NO_ERROR) 301 { 302 rc = SetExecName(ldrpFileNameBuf); 303 if (rc != NO_ERROR) 304 kprintf(("myldrOpen-%d: pe.exe - failed to set pe.exe as execname. rc=%d\n", cNesting)); 305 } 306 else 307 kprintf(("myldrOpen-%d: pe.exe - failed to add programname as argument. rc=%d\n", cNesting, rc)); 308 goto cleanup_noerror; 213 309 } 214 310 } 311 else 312 kprintf(("myldrOpen-%d: pe.exe - couldn't find/open pe.exe\n", cNesting)); 215 313 } 216 rfree(pszBuffer); 217 return NO_ERROR; 314 goto cleanup; 218 315 } 219 else 316 /** @sketch End of PE Loading. */ 317 318 319 /** @sketch 320 * ELF image? 321 */ 322 if (*u1.pul == ELFMAGICLSB) 220 323 { 324 if (isELFDisabled()) 325 goto cleanup_noerror; 326 221 327 /* 222 * ELF image?328 * ELF signature found. 223 329 */ 224 if (pach[0] == ELFMAG0 && pach[1] == ELFMAG1 && pach[2] == ELFMAG2 && pach[3] == ELFMAG3) 330 kprintf(("myldrOpen-%d: ELF image! - not implemented yet!\n", cNesting)); 331 332 /* 333 * Do nothing more yet. NEED AN ELF LOADER!!! 334 */ 335 goto cleanup; 336 } 337 338 339 /** @sketch 340 * Java image? 341 */ 342 if (*u1.pul == 0xBEBAFECAUL) //CAh FEh BAh BEh 343 { 344 char *pszName = NULL; 345 int cchName; 346 347 if (isJAVADisabled()) 348 goto cleanup_noerror; 349 350 /** @sketch 351 * Java signature found. 352 * Copy the name to a temporary buffer. (only if necessary) 353 * Remove the extention (.class) and insert a space between the name and the path. 354 * (This is the needed processing of the class filename to make it a classpath 355 * entry (path) and a class name (filename).) 356 * Try find the java executor in current dir or PATH: java.exe 357 */ 358 kprintf(("myldrOpen-%d: Jave image!\n", cNesting)); 359 360 if (isLdrStateExecPgm() && fTkExecPgm) 225 361 { 226 /* 227 * ELF signature found. 362 /* Ooops we had to get the file name from the MFT. ldrpFileNameBuf is allways uppercased... */ 363 /* MFT seems to hold uppercased filenames! ARG! But (by pure luck?) achTkExecPgmArguments is 364 * not uppercased (yet). Nothing could be simpler! 228 365 */ 229 kprintf(("ldrOpen: ELF executable! - not implemented yet!\n")); 230 231 /* 232 * Do nothing more yet. NEED AN ELF LOADER!!! 366 #if 1 367 psz3 = achTkExecPgmArguments; 368 #elif 0 369 psz3 = SecPathFromSFN(*phFile); 370 if (psz3 == NULL) 371 psz3 = ldrpFileNameBuf; 372 #else 373 psz3 = ldrpFileNameBuf; 374 #endif 375 cchName = strlen(psz3); 376 pszName = (char*)rmalloc(cchName + 2); 377 if (pszName == NULL) 378 { 379 rc = ERROR_NOT_ENOUGH_MEMORY; 380 goto cleanup; 381 } 382 memcpy(pszName, psz3, cchName+1); 383 384 psz = pszName + strlen(pszName) - 1; 385 while (psz > pszName && *psz != '.' && *psz != '\\' && *psz != '/') 386 psz--; 387 if (*psz == '.') 388 { 389 cchName = psz - pszName; 390 *psz-- = '\0'; 391 while (psz > pszName && *psz != '\\' && *psz != '/') 392 psz--; 393 394 /* check for root and evt. make room for an extra slash. */ 395 if (psz - pszName == 2) 396 { 397 memmove(psz + 1, psz, cchName - 1); 398 *psz++ = '\\'; 399 } 400 } 401 /* check if no path */ 402 if (psz == pszName) 403 memmove(pszName + 1, pszName, cchName + 1); 404 *psz = ' '; 405 } 406 407 ldrClose(*phFile); 408 rc = ldrOpen(phFile, ".\\JAVA.EXE", pfl); 409 if (rc != NO_ERROR) 410 rc = OpenPATH(phFile, "JAVA.EXE", pfl); 411 if (rc == NO_ERROR) 412 { 413 kprintf(("myldrOpen-%d: java - %s\n", cNesting, ldrpFileNameBuf)); 414 415 /** @sketch 416 * To be able to execute any given class name we'll have to pass in the 417 * directory as -classpath. But -classpath seems to override the default 418 * and environmental CLASSPATHs. So, we'll have to pass in the value of 419 * the CLASSPATH env.var. or generate the default class path (what ever that is). 420 * 233 421 */ 234 rfree(pszBuffer); 235 return NO_ERROR; 422 if (isLdrStateExecPgm() && fTkExecPgm) 423 { 424 psz = u1.pach; 425 426 /* 427 * Get classpath and add it as a parameter 428 */ 429 strcpy(u1.pach, "-classpath "); 430 psz = u1.pach + strlen(u1.pach); 431 432 psz3 = (char*)ScanEnv(GetEnv(TRUE), "CLASSPATH"); 433 if (psz3 != NULL) 434 { /* environment variable set */ 435 if (strlen(psz3) > 640 - 11 - 1 - cchName) //check for overflow 436 { // TODO? should reallocate... 437 memcpy(psz, psz3, 640 - 11 - 1 - cchName); 438 psz[640 - 11 - 1 - cchName] = '\0'; 439 } 440 else 441 strcpy(psz, psz3); 442 psz += strlen(psz); 443 } 444 else 445 { 446 /* Make default classpath by taking the java.exe path + '..\lib\classes.zip' */ 447 strcpy(psz, ldrpFileNameBuf); 448 psz3 = psz + strlen(psz) - 1; 449 while (psz3 > psz && *psz3 != '\\' && *psz3 != '/') 450 psz3--; 451 strcpy(++psz3, "..\\lib\\classes.zip"); 452 psz = psz3 + strlen(psz3); 453 } 454 455 /* 456 * Add the class directory (as the last classpath entry) and the class name. 457 * (Note. I may happen that there is no directory, but that don't matter 458 * a space is allways preceding the class name.) 459 */ 460 *psz++ = ';'; 461 strcpy(psz, pszName); 462 if (pszName != NULL) 463 rfree(pszName); 464 465 /* 466 * Setup JAVA.EXE as executable with the parameters we've build. 467 */ 468 rc = AddArgsToFront(2, ldrpFileNameBuf, u1.pach); 469 kprintf(("myldrOpen-%d: java - Exe: %s Args: %s\n", cNesting, ldrpFileNameBuf, u1.pach)); 470 if (rc == NO_ERROR) 471 { 472 rc = SetExecName(ldrpFileNameBuf); 473 if (rc != NO_ERROR) 474 kprintf(("myldrOpen-%d: java - failed to set java.exe as execname. rc=%d\n", cNesting, rc)); 475 } 476 else 477 kprintf(("myldrOpen-%d: java - failed to setup the parameters. rc=%d\n", cNesting, rc)); 478 479 goto cleanup_noerror; 480 } 236 481 } 482 else 483 kprintf(("myldrOpen-%d: java - couldn't find/open java.exe\n", cNesting)); 484 485 486 /** @sketch 487 * End of Java loading. (return) 488 */ 489 if (pszName != NULL) 490 rfree(pszName); 491 goto cleanup; 237 492 } 493 238 494 } 495 else 496 { 497 /** @sketch 498 * ELSE - the reading size of a DOS header failed or file is smaller than the dos header. 499 * IF read failed or filesize is less than 4 bytes THEN 500 * return no_error to the caller. 501 * ENDIF 502 */ 503 #ifdef DEBUG 504 if (rc != NO_ERROR) 505 { 506 kprintf(("myldrOpen-%d: ldrRead failed cbRead=%d, cbFile=%d, rc=%d\n", cNesting, cbRead, cbFile, rc)); 507 goto cleanup_noerror; 508 } 509 if (cbRead < 4) 510 { 511 kprintf(("myldrOpen-%d: File too small! cbFile=%d\n", cNesting, cbFile)); 512 goto cleanup_noerror; 513 } 514 #else 515 if (rc != NO_ERROR || cbRead < 4) //just forget files less than 4 bytes! 516 goto cleanup_noerror; 517 #endif 518 } 519 /** @sketch ENDIF (dos header read) */ 520 521 239 522 240 523 /* 241 * Only unreconized files and readerrorpasses this point!524 * Only unreconized files passes this point! 242 525 * 243 526 * * Fileformats with lower priority should reside here. * … … 245 528 */ 246 529 247 /* 248 * If the initial readoperation failed try to read a smaller amount, in case it is a small script... 249 * 4 bytes is a small amount isn't it? 250 */ 251 if (rc != NO_ERROR) 530 /** @sketch 531 * UNIX styled script? 532 * - Starts with a hash (#) 533 * - And we're loading an EXE 534 * - And we're either in QAppType or ExecPgm state. 535 * - And that a bang (!) is the first char after the hash (ignoring blanks). 536 */ 537 if (*u1.pach == '#' 538 && isLdrStateLoadingEXE() 539 && (isLdrStateQAppType() || isLdrStateExecPgm()) 540 ) 252 541 { 253 kprintf(("ldrOpen: first ldrread failed with rc=%d. tries to read 4 byte.\n", rc)); 254 cchRead = 4; 255 if ((rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL)) != NO_ERROR) 256 kprintf(("ldrOpen: second ldrread failed with rc=%d.\n ", rc)); 257 } 258 259 /* 260 * Now we'll try again, UNIX styled script? 261 */ 262 if (rc == NO_ERROR && *pach == '#' && pach[1] == '!') 263 { 542 if (isUNIXScriptDisabled()) 543 goto cleanup_noerror; 264 544 /* 265 * UNIX styled script? 266 * FIXME! Must be more than 64 bytes long? 267 * No options! 268 * Firstline < 64 bytes! 545 * Look for a bang (!). Tabs and spaces are skipped, anything else result in error. 269 546 */ 270 kprintf(("ldrOpen: unix script?\n"));271 cchRead = min(cbFile, 256);272 rc = ldrRead(*phFile, 0UL, pach, 0UL, cchRead, NULL);273 if ( rc == NO_ERROR)547 psz = u1.pach + 1; 548 while ((*psz == ' ' || *psz == '\t') && psz - u1.pach < cbRead) 549 psz++; 550 if (*psz == '!') 274 551 { 275 char *pszStart = pach+2; 276 kprintf(("ldrOpen: script debug 1\n")); 277 278 /* Make sure we don't read to much... */ 279 pszBuffer[cchRead] = '\0'; 280 281 /* 282 * Skip blanks 552 /** @sketch Found UNIX styled script! */ 553 554 /** @sketch 555 * Read more of the script if necessary. (max is 256 chars (- Linux max is 127)) 556 * Terminate the string read from the file to make sure with stop somewhere! 283 557 */ 284 pszStart = pszBuffer + 2; /* skips the "#!" stuff. */ 285 while (*pszStart != '\0' && (*pszStart == ' ' || *pszStart == '\t')) 286 pszStart++; 287 kprintf(("ldrOpen: script debug 2\n")); 288 289 /* anything left on the line? */ 290 if (*pszStart != '\0' && *pszStart != '\r' && *pszStart != '\n') 558 if (cbRead < cbFile /*&& cbRead != 256*/) 291 559 { 292 char * pszEnd; /* Pointer to the end of the string(s) when the next step is finished. */ 293 unsigned cchToAdd = 1; /* Chars to add */ 294 BOOL fFirst = TRUE; /* Set if a '\0' has not been set yet. 295 * If this is clear, there are one or more parameters after the interpreter name. */ 296 297 /* 298 * find linesize and make parameters ready for copying 560 cbRead = min(256, cbFile); 561 rc = ldrRead(*phFile, 0UL, u1.pach, 0UL, cbRead, NULL); 562 } 563 u1.pach[cbRead] = '\0'; 564 565 if (rc == NO_ERROR) 566 { 567 /** @sketch 568 * Parse out filename and optional arguments (if any). 569 * The result of the parsing is that: 570 * psz will point at the executable name. 571 * psz2 will point at the arguments. 572 * Both strings are trimmed. 299 573 */ 300 pszEnd = pszStart; 301 kprintf(("ldrOpen: script debug 3\n")); 302 while (*pszEnd != '\0' && *pszEnd != '\r' && *pszEnd != '\n') 574 psz++; /* psz points to the bang, skip it. */ 575 while (*psz == ' ' || *psz == '\t') /* skip blanks after bang */ 576 psz++; 577 if (*psz == '\r' || *psz == '\n' || *psz == '\0') /* End-of-line? */ 303 578 { 304 if (fFirst && (*pszEnd == ' ' || *pszEnd == '\t')) 579 kprintf(("myldrOpen-%d: script no executable name.\n", cNesting)); 580 goto cleanup_noerror; /* other error code? */ 581 } 582 psz2 = psz + 1; /* Not end-of-line, so add 1 before searching for args. */ 583 while (*psz2 != '\0' && *psz2 != '\n' && *psz2 != '\r' /* skip executable name. */ 584 && *psz2 != ' ' && *psz2 != '\t') 585 psz2++; 586 while (*psz2 == ' ' || *psz2 == '\t') /* skip blanks after executable - pad them with '\0'! */ 587 *psz2++ = '\0'; 588 589 psz3 = psz2; 590 while (*psz3 != '\n' && *psz3 != '\r' && *psz3 != '\0') /* find end of parameters and terminate the string. */ 591 psz3++; 592 *psz3 = '\0'; 593 while (psz3 >= psz2 && (*psz3 == '\0' || *psz3 == ' ' || *psz3 == '\t')) /* trim args */ 594 *psz3-- = '\0'; 595 596 597 /** @sketch 598 * IF tkExecPgm THEN 599 * Correct parameters - ie. add exec name (as argv[0]), 600 * arguments (psz2) as argv[1+], old exec name, and finally 601 * the existing parameters (current argv[1+]). 602 * Set the executable name. 603 * ENDIF 604 * Open the new executable file recursively. (psz) 605 */ 606 if (isLdrStateExecPgm()) 607 { 608 if (*psz2) 609 rc = AddArgsToFront(3, psz, psz2, achTkExecPgmFilename); 610 else 611 rc = AddArgsToFront(2, psz, achTkExecPgmFilename); 612 if (rc != NO_ERROR) 305 613 { 306 *pszEnd = '\0'; 307 fFirst = FALSE; 308 if (pszEnd[1] == '\0' || pszEnd[1] == '\r' || pszEnd[1] == '\n') 309 fFirst = TRUE; 614 kprintf(("myldrOpen-%d: AddArgsToFront failed with rc=%d\n", cNesting)); 615 goto cleanup_noerror; 310 616 } 311 312 /* next */ 313 pszEnd++; 314 cchToAdd++; 617 rc = SetExecName(psz); 618 if (rc != NO_ERROR) 619 kprintf(("myldrOpen-%d: SetExecName failed with rc=%d\n", cNesting)); 315 620 } 316 *pszEnd = '\0'; 317 kprintf(("ldrOpen: script debug 4\n")); 318 319 /* 320 * If ldrQueryApp type we don't have any ExecPgm buffer we need to mess with. 321 * We'll simply try open the the interpreter. 322 */ 323 if (fQAppType) 621 ldrClose(*phFile); 622 rc = myldrOpen(phFile, psz, pfl); 623 if (rc != NO_ERROR) 324 624 { 325 rc = ldrClose(*phFile); 326 rc = ldrOpen(phFile, pszStart, param3); /* FIXME, recusion! check that name not equal! Use flags to prevent race? */ 327 } 328 else 329 { 330 /* 331 * Find the ExecPgm buffer. 332 */ 333 pBuffer = QueryBufferPointerFromFilename(pszFilename); 334 kprintf(("ldrOpen: script debug 5\n")); 335 if (pBuffer != NULL) 625 psz2 = psz + strlen(psz); 626 if (psz + 4 >= psz2 || strcmp(psz2 - 4, ".EXE") != 0) 336 627 { 337 unsigned cchArguments = getArgsLength(pBuffer->achArgs); /* minus the first argument. */ 338 unsigned cchScriptnameDelta = strlen(pBuffer->szFilename) - strlen(pBuffer->achArgs); /* scriptname size difference. */ 339 340 kprintf(("ldrOpen: script debug 6\n")); 341 342 /* 343 * Is there enough space in the struct? 344 */ 345 if (cchArguments + cchToAdd + cchScriptnameDelta < sizeof(pBuffer->achArgs)) 346 { 347 kprintf(("ldrOpen: script debug 7\n")); 348 /* 349 * Open the interpreter. 350 */ 351 rc = ldrClose(*phFile); 352 rc = ldrOpen(phFile, pszStart, param3); /* FIXME, recusion! check that name not equal! Use flags to prevent race? */ 353 if (rc == NO_ERROR) 354 { 355 kprintf(("ldrOpen: script debug 8\n")); 356 /* Make space for the addition arguments. */ 357 #ifdef DEBUG 358 char *psz = &pBuffer->achArgs[0]; 359 int i = 0; 360 while (*psz != '\0') 361 { 362 kprintf(("Arg %d: %s\n", i++, psz)); 363 psz += 1 + strlen(psz); 364 } 365 #endif 366 memmove(&pBuffer->achArgs[cchToAdd + cchScriptnameDelta], 367 &pBuffer->achArgs[0], cchArguments); 368 369 /* 370 * Copy the arguments. 371 */ 372 kprintf(("ldrOpen: script debug 8\n")); 373 memcpy(&pBuffer->achArgs[0], pszStart, cchToAdd); /* Interpreter with arguments */ 374 if (!fFirst) 375 pBuffer->achArgs[cchToAdd - 1] = ' '; 376 strcpy(&pBuffer->achArgs[cchToAdd], pszFilename); /* Scriptname */ 377 kprintf(("ldrOpen: script debug a\n")); 378 379 #ifdef DEBUG 380 psz = &pBuffer->achArgs[0]; 381 i = 0; 382 while (*psz != '\0') 383 { 384 kprintf(("Arg %d: %s\n", i++, psz)); 385 psz += 1 + strlen(psz); 386 } 387 #endif 388 } 389 else 390 kprintf(("ldrOpen: failed to open interpreter (%s), rc=%d\n", pszStart, rc)); 391 } 392 else 393 { 394 kprintf(("ldrOpen: Argument buffer too small, %d\n", cchArguments + cchToAdd)); 395 rc = ERROR_BAD_EXE_FORMAT; 396 } 628 strcpy(psz2, ".EXE"); 629 rc = myldrOpen(phFile, psz, pfl); 630 *psz2 = '\0'; 397 631 } 398 632 else 633 psz2 = NULL; 634 635 //should we search the PATH??? For a starting, we'll do it. 636 if (rc != NO_ERROR 637 && (rc = OpenPATH(phFile, psz, pfl)) != NO_ERROR 638 && psz2 != NULL) 399 639 { 400 kprintf(("ldrOpen: QueryBufferPointerFromFilename failed.\n"));401 rc = ERROR_BAD_EXE_FORMAT; /*?*/640 *psz2 = '.'; 641 rc = OpenPATH(phFile, psz, pfl); 402 642 } 403 643 } … … 405 645 else 406 646 { 407 kprintf((" ldrOpen: no interpereter on the first line.\n"));408 rc = ERROR_BAD_EXE_FORMAT; /*?*/647 kprintf(("myldrOpen-%d: script - failed to read more of the script!, rc=%d cbRead=%d cbFile=%d.\n", 648 cNesting, rc, cbRead, cbFile)); 409 649 } 650 651 goto cleanup; 410 652 } 411 653 else 412 654 { 413 kprintf((" ldrOpen: read of min(cbFile, 256) = %d failed, rc = %d\n", cchRead, rc));655 kprintf(("myldrOpen-%d: script - hash found but no bang (!).\n", cNesting)); 414 656 } 415 } /* else inn other formats here. */ 416 rfree(pszBuffer); 417 } 657 } /**@sketch ENDIF - UNIX styled script. */ 658 659 660 661 /** @sketch 662 * REXX script? 663 * - Starts with a REXX start comment ('/','*') 664 * - And we're loading an EXE 665 * - And we're either in QAppType or ExecPgm state. 666 * - Extention: 667 * .RX and .REX are known to be pure REXX scripts. 668 * While .CMD has to invoked used the commandline OS2_SHELL or COMSPEC variable. 669 */ 670 psz2 = pszFilename + strlen(pszFilename) - 1; 671 while (psz2 > pszFilename && *psz2 != '.') 672 psz2--; 673 if (*psz2 == '.' 674 && *u1.pach == '/' && u1.pach[1] == '*' 675 && isLdrStateLoadingEXE() 676 && (isLdrStateQAppType() || isLdrStateExecPgm()) 677 && (stricmp(psz2, ".RX") == 0 || stricmp(psz2, ".REX") == 0) 678 ) 679 { 680 if (isREXXScriptDisabled()) 681 goto cleanup_noerror; 682 683 /** @sketch 684 * Found REXX styled script! 685 * Find the REXX interpreter. We'll use kRx.exe to execute the REXX scripts. 686 * (This interpreter could be embedded as a child of ModuleBase as it turned out 687 * to be quite small about 700 bytes.) 688 */ 689 kprintf(("myldrOpen-%d: Found REXX script\n", cNesting)); 690 ldrClose(*phFile); 691 psz = "KRX.EXE"; 692 rc = ldrOpen(phFile, psz, pfl); 693 if (rc != NO_ERROR) 694 rc = OpenPATH(phFile, psz, pfl); 695 696 /** @sketch 697 * IF tkExecPgm THEN 698 * Correct parameters - ie. add exec name (as argv[0]), old exec name, 699 * and finally the existing parameters (current argv[1+]). 700 * Set the executable name. 701 * ENDIF 702 */ 703 if (rc == NO_ERROR && isLdrStateExecPgm()) 704 { 705 rc = AddArgsToFront(2, ldrpFileNameBuf, achTkExecPgmFilename); 706 if (rc != NO_ERROR) 707 { 708 kprintf(("myldrOpen-%d: AddArgsToFront failed with rc=%d\n", cNesting)); 709 goto cleanup_noerror; 710 } 711 rc = SetExecName(ldrpFileNameBuf); 712 if (rc != NO_ERROR) 713 kprintf(("myldrOpen-%d: SetExecName failed with rc=%d\n", cNesting)); 714 715 goto cleanup_noerror; 716 } 717 goto cleanup; 718 } /**@sketch ENDIF - REXX styled script. */ 719 720 721 /* 722 * Cleanup with rc set to NO_ERROR. 723 */ 724 cleanup_noerror: 725 rc = NO_ERROR; 726 727 /* 728 * Cleanup without having rc set to NO_ERROR. 729 * Decrement the nesting count. 730 */ 731 cleanup: 732 rfree(u1.pach); 733 cNesting--; 734 } 735 #ifdef DEBUG 736 else if (cNesting >= 3) 737 kprintf(("myldrOpen-%d: cNesting = %d, which is too deep!\n", cNesting, cNesting)); 738 #endif 739 740 ret: 741 /** @sketch 742 * Return rc. 743 */ 418 744 return rc; 419 745 } … … 421 747 422 748 /** 423 * Get the lenght of the arguments. 424 * @returns Lenght in char, includes the two '\0's. 425 * @param pachArgs Pointer to the ASCIIZs which makes up the arguments. 426 * @status completely implemented. 749 * Adds new arguments to the front of the startup arguments for the program about to be 750 * executed. 751 * 752 * @returns OS/2 return code. 753 * @param cArgs Count of arguments to add. At least 1!!! 754 * @param ... Pointers to the arguments to add. 755 * The first argument have to be the executable name. This have to the 756 * the only argument in the first string. 757 * The other arguements are space separated, so you could add a bunch 758 * of arguments in a single string! 759 * The last argument should be the old first parameter if this is to be 760 * preserved. The old first parameter is overwritten since it's 761 * normally the executable name. 762 * 763 * @status completly implemented. 427 764 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no) 765 * @remark Implementation note: 766 * The arguments convention is as follows: 767 * First argument, which should be the executable name, is terminated with a '\0'. 768 * It starts at offset 0 into the argument buffer, of course. 769 * All other arguemnts are separated by a space and follows the immediately after the 770 * first argument. 771 * The arguments are terminated by a double nulltermination: '\0\0'. 428 772 */ 429 static unsigned getArgsLength(const char *pachArgs)773 APIRET AddArgsToFront(int cArgs, ...) 430 774 { 431 unsigned cch = 1; 432 const char *psz = pachArgs; 433 775 va_list vaarg; /* Variable length argument list. */ 776 int cchOldArgs; /* Length of the old arguments (including the first argument). */ 777 /* cchOldArgs = 1 means no arguments. It don't include the very last '\0' */ 778 /* (remember argumets are terminated with two '\0's). */ 779 int iSecondArg; /* Index of the second argument. (Used to skip the first argument.) */ 780 /* Used first on the original arguments and them when adding the first */ 781 /* new argument. */ 782 int cchNewArgs; /* Length of the new arguments to be inserted. */ 783 int i; /* Loop variable. Current function argument. */ 784 char * psz; /* General string pointer. */ 785 786 787 /** @sketch 788 * Assert that we're in the right state. 789 * Calc the length of the existing parameters. 790 * Calc the length of the new arguments to determin. 791 * Assert that the new arguments have length > 0. 792 */ 793 #ifdef DEBUG 794 if (!isLdrStateExecPgm()) 795 { 796 kprintf(("AddArgsToFront: not in tkExecPgm state.\n")); 797 return ERROR_INVALID_PARAMETER; 798 } 799 #endif 800 if (!fTkExecPgm) 801 { 802 kprintf(("AddArgsToFront: called when not in tkExecPgm data is invalid!\n")); 803 return ERROR_INVALID_PARAMETER; 804 } 805 806 iSecondArg = strlen(&achTkExecPgmArguments[0]) + 1; 807 psz = &achTkExecPgmArguments[iSecondArg]; 434 808 while (*psz != '\0') 435 { 436 register unsigned cch2 = strlen(psz); 437 cch += cch2; 438 psz += cch2 + 1; 439 } 440 441 return cch; 809 psz += strlen(psz) + 1; 810 cchOldArgs = psz - &achTkExecPgmArguments[iSecondArg]; 811 812 va_start(vaarg, cArgs); 813 for (cchNewArgs = i = 0; i < cArgs; i++) 814 cchNewArgs += strlen(va_arg(vaarg, char *)) + 1; /* 1 is for space or '\0'. */ 815 va_end(vaarg); 816 #ifdef DEBUG 817 if (cchNewArgs == 0) 818 { 819 kprintf(("AddArgsToFront: the size of the arguments to add is zero!\n")); 820 return ERROR_INVALID_PARAMETER; 821 } 822 #endif 823 824 825 /** @sketch 826 * Check if we have enough room for the new arguments. Fail if not enough. 827 * Move the existing arguments to make room for the new ones. 828 * !IMPORTANT! The first existing arguments (executable name) is skipped !IMPORTANT! 829 * !IMPORTANT! in this move as this have to be re-added in this call! !IMPORTANT! 830 */ 831 if (cchOldArgs + cchNewArgs + 1 > CCHARGUMENTS) 832 { 833 kprintf(("AddArgsToFront: argument buffer is too small to hold the arguments to add, cchOldArgs=%d, cchNewArgs=%d\n", 834 cchOldArgs, cchNewArgs)); 835 return ERROR_BAD_ARGUMENTS; 836 } 837 838 if (cchOldArgs > 0) 839 { 840 memmove(&achTkExecPgmArguments[cchNewArgs], &achTkExecPgmArguments[iSecondArg], 841 cchOldArgs + 1); 842 } 843 else 844 achTkExecPgmArguments[cchNewArgs] = '\0'; 845 846 847 /** @sketch 848 * Copy new arguments. 849 * Since the first argument is special case we'll do it separately. (Uses '\0' as separator.) 850 * We assume that the entire first argument passed into this function should be the first argument! 851 * (This don't have to be true for the other arguments since these are space separated. You could 852 * pass in more than argument in a single string.) 853 * Loop thru the rest of the new arguments and add them with space as separator. 854 */ 855 va_start(vaarg, cArgs); 856 psz = va_arg(vaarg, char *); 857 memcpy(&achTkExecPgmArguments[0], psz, (i = strlen(psz) + 1)); 858 psz = &achTkExecPgmArguments[i]; 859 860 for (i = 1; i < cArgs; i++) 861 { 862 if (i > 1) *psz++ = ' '; //Add space if not second argument. 863 strcpy(psz, va_arg(vaarg, char *)); 864 psz += strlen(psz); 865 } 866 va_end(vaarg); 867 if (cchOldArgs > 0) *psz++ = ' '; //Add space if old arguments 868 869 #ifdef DEBUG /* assertion */ 870 if (psz != &achTkExecPgmArguments[cchNewArgs]) 871 { 872 kprintf(("AddArgsToFront: !Assertion failed! psz didn't end up where it should! (psz -> %d should be %d)\n", 873 psz - &achTkExecPgmArguments[0], cchNewArgs)); 874 if (cchOldArgs <= 1) 875 psz[0] = psz[1] = '\0'; 876 } 877 #endif 878 879 return NO_ERROR; 442 880 } 881 882 883 /** 884 * Sets the executable name of the module. 885 * This function is normally invoked after a different executable than the one requested was 886 * opened. It does _NOT_ set the new executable name as the first argument, since it is more 887 * convenient to this while calling AddArgsToFront to add other arguments. 888 * 889 * @returns OS/2 return code. 890 * @param pszExecName Pointer to new executable name. 891 * @status completly implemented. 892 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no) 893 * @remark . 894 */ 895 APIRET SetExecName(const char *pszExecName) 896 { 897 #ifdef DEBUG 898 int cch; 899 cch = strlen(pszExecName); 900 if (cch > CCHMAXPATH) 901 { 902 kprintf(("ChangeExecName: filename is too long! cch=%d. name=%s\n", cch, pszExecName)); 903 return ERROR_FILENAME_EXCED_RANGE; 904 } 905 if (!isLdrStateExecPgm()) 906 { 907 kprintf(("ChangeExecName: called when not in tkExecPgm state!!! FATAL ERROR!\n")); 908 return ERROR_INVALID_PARAMETER; 909 } 910 #endif 911 if (!fTkExecPgm) 912 { 913 kprintf(("ChangeExecName: called when not in tkExecPgm data is invalid!!! FATAL ERROR!\n")); 914 return ERROR_INVALID_PARAMETER; 915 } 916 917 strcpy(achTkExecPgmFilename, pszExecName); 918 919 return 0; 920 } 921 922 923 /** 924 * Opens a file using the PATH environment variable of the current process. 925 * @returns OS2 return code. 926 * @param phFile Pointer to filehandle. The filehandle is set to the SFN for the opened 927 * file on successful return. 928 * The filehandle is 0 on failure. 929 * @param pszFilename Pointer to filename buffer. This will hold the filename on input. 930 * On successful return it holds the filepath found. 931 * On failiure it's undefined. 932 * @param pfl Some flags set by ldrOpen. 933 * @sketch stub 934 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no) 935 * @remark 936 */ 937 APIRET OpenPATH(PSFN phFile, char *pszFilename, PULONG pfl) 938 { 939 APIRET rc; 940 USHORT TCBFailErr_save; 941 int cchFile; /* Filename length + 1. */ 942 const char *pszFile; /* Pointer to filename portion. */ 943 const char *pszPath = ScanEnv(GetEnv(FALSE), "PATH"); /* Current Process environment? */ 944 945 /**@sketch 946 * No PATH environment. 947 */ 948 if (pszPath == NULL) 949 return ERROR_FILE_NOT_FOUND; 950 951 /**@sketch 952 * Skip any paths in the filename. 953 */ 954 pszFile = pszFilename + (cchFile = strlen(pszFilename)); 955 while (pszFile >= pszFilename && *pszFile != '\\' && *pszFile != '/') 956 pszFile--; 957 cchFile -= pszFile - pszFilename; 958 pszFile++; 959 960 /**@sketch 961 * We'll have to save the TCBFailErr since we don't want to cause 962 * Hard Errors while searching invalid paths, etc. (ldrOpenPath does this!) 963 */ 964 TCBFailErr_save = tcbGetTCBFailErr(tcbGetCur()); 965 966 /**@ sketch 967 * Loop thru the PATH trying to open the specified file in each 968 * directory. 969 */ 970 while (*pszPath != '\0') 971 { 972 const char * pszNext; 973 int cchPath; 974 char chEnd; 975 register char ch; 976 977 /* 978 * Find end of this path. 979 */ 980 while (*pszPath == ' ') pszPath++; //skip leading spaces. 981 if (*pszPath == '"') 982 { 983 chEnd = '"'; 984 pszPath++; 985 } 986 else 987 chEnd = ';'; 988 pszNext = pszPath; 989 while ((ch = *pszNext) != chEnd && ch != '\0') 990 pszNext++; 991 992 cchPath = pszNext - pszPath; 993 if (chEnd == '"') 994 { 995 /* Skip anything between the " and the ; or string end. */ 996 while ((ch = *pszNext) != ';' && ch != '\0') 997 pszNext++; 998 } 999 else 1000 { 1001 /* Trim the string. */ 1002 while (cchPath > 0 && pszPath[cchPath-1] == ' ') //?? 1003 cchPath--; 1004 } 1005 1006 /* 1007 * No length? No Path! Or path'\'filename too long? => Next 1008 */ 1009 if (cchPath > 0 && cchPath + cchFile + 1 < CCHMAXPATH) 1010 { 1011 static char achFilename[CCHMAXPATH]; 1012 /* 1013 * Build filename 1014 */ 1015 memcpy(achFilename, pszPath, cchPath); 1016 if ((ch = achFilename[cchPath - 1]) == '\\' || ch == '/') 1017 cchPath--; 1018 else 1019 achFilename[cchPath] = '\\'; 1020 memcpy(&achFilename[cchPath + 1], pszFile, cchFile); /* cchFile = length + 1; hence we copy the terminator too. */ 1021 1022 /* 1023 * Try open the file. 1024 */ 1025 rc = myldrOpen(phFile, achFilename, pfl); 1026 switch (rc) 1027 { 1028 case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: case ERROR_ACCESS_DENIED: case ERROR_INVALID_ACCESS: 1029 case ERROR_INVALID_DRIVE: case ERROR_NOT_DOS_DISK: case ERROR_REM_NOT_LIST: case ERROR_BAD_NETPATH: 1030 case ERROR_NETWORK_BUSY: case ERROR_DEV_NOT_EXIST: case ERROR_TOO_MANY_CMDS: case ERROR_ADAP_HDW_ERR: 1031 case ERROR_UNEXP_NET_ERR: case ERROR_BAD_REM_ADAP: case ERROR_NETNAME_DELETED: case ERROR_BAD_DEV_TYPE: 1032 case ERROR_NETWORK_ACCESS_DENIED: case ERROR_BAD_NET_NAME: case ERROR_TOO_MANY_SESS: case ERROR_REQ_NOT_ACCEP: 1033 case ERROR_INVALID_PASSWORD: case ERROR_OPEN_FAILED: case ERROR_INVALID_NAME: case ERROR_FILENAME_EXCED_RANGE: 1034 case ERROR_VC_DISCONNECTED: 1035 break; 1036 1037 case NO_ERROR: 1038 strcpy(pszFilename, achFilename); 1039 default: 1040 tcbSetTCBFailErr(tcbGetCur(), TCBFailErr_save); 1041 return rc; 1042 } 1043 } 1044 #ifdef DEBUG 1045 else if (cchPath > 0) kprintf(("OpenPATH: Path component is too long\n")); 1046 #endif 1047 1048 /* 1049 * Next 1050 */ 1051 if (*pszNext == '\0') 1052 break; 1053 pszPath = pszNext + 1; 1054 } 1055 1056 1057 /* 1058 * File is not found. 1059 */ 1060 *phFile = 0; 1061 tcbSetTCBFailErr(tcbGetCur(), TCBFailErr_save); 1062 return ERROR_FILE_NOT_FOUND; 1063 }
Note:
See TracChangeset
for help on using the changeset viewer.