Changeset 21464 for trunk/src/kernel32/wprocess.cpp
- Timestamp:
- Sep 29, 2010, 5:09:55 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/wprocess.cpp
r21463 r21464 50 50 #include "initterm.h" 51 51 #include "directory.h" 52 #include "shellapi.h" 52 53 53 54 #include <win\ntddk.h> … … 85 86 PCSTR pszCmdLineA; /* ASCII/ANSII commandline. */ 86 87 PCWSTR pszCmdLineW; /* Unicode commandline. */ 88 char **__argvA = NULL; /* command line arguments in ANSI */ 89 int __argcA = 0; /* number of arguments in __argcA */ 87 90 88 91 //Process database … … 1362 1365 1363 1366 1367 /************************************************************************* 1368 * CommandLineToArgvW (re-exported as [SHELL32.7]) 1369 */ 1370 /************************************************************************* 1371 * 1372 * We must interpret the quotes in the command line to rebuild the argv 1373 * array correctly: 1374 * - arguments are separated by spaces or tabs 1375 * - quotes serve as optional argument delimiters 1376 * '"a b"' -> 'a b' 1377 * - escaped quotes must be converted back to '"' 1378 * '\"' -> '"' 1379 * - an odd number of '\'s followed by '"' correspond to half that number 1380 * of '\' followed by a '"' (extension of the above) 1381 * '\\\"' -> '\"' 1382 * '\\\\\"' -> '\\"' 1383 * - an even number of '\'s followed by a '"' correspond to half that number 1384 * of '\', plus a regular quote serving as an argument delimiter (which 1385 * means it does not appear in the result) 1386 * 'a\\"b c"' -> 'a\b c' 1387 * 'a\\\\"b c"' -> 'a\\b c' 1388 * - '\' that are not followed by a '"' are copied literally 1389 * 'a\b' -> 'a\b' 1390 * 'a\\b' -> 'a\\b' 1391 * 1392 * Note: 1393 * '\t' == 0x0009 1394 * ' ' == 0x0020 1395 * '"' == 0x0022 1396 * '\\' == 0x005c 1397 */ 1398 LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs) 1399 { 1400 DWORD argc; 1401 HGLOBAL hargv; 1402 LPWSTR *argv; 1403 LPCWSTR cs; 1404 LPWSTR arg,s,d; 1405 LPWSTR cmdline; 1406 int in_quotes,bcount; 1407 1408 if (*lpCmdline==0) { 1409 /* Return the path to the executable */ 1410 DWORD size; 1411 1412 hargv=0; 1413 size=16; 1414 do { 1415 size*=2; 1416 hargv=GlobalReAlloc(hargv, size, 0); 1417 argv=(LPWSTR*)GlobalLock(hargv); 1418 } while (GetModuleFileNameW((HMODULE)0, (LPWSTR)(argv+1), size-sizeof(LPWSTR)) == 0); 1419 argv[0]=(LPWSTR)(argv+1); 1420 if (numargs) 1421 *numargs=2; 1422 1423 return argv; 1424 } 1425 1426 /* to get a writeable copy */ 1427 argc=0; 1428 bcount=0; 1429 in_quotes=0; 1430 cs=lpCmdline; 1431 while (1) { 1432 if (*cs==0 || ((*cs==0x0009 || *cs==0x0020) && !in_quotes)) { 1433 /* space */ 1434 argc++; 1435 /* skip the remaining spaces */ 1436 while (*cs==0x0009 || *cs==0x0020) { 1437 cs++; 1438 } 1439 if (*cs==0) 1440 break; 1441 bcount=0; 1442 continue; 1443 } else if (*cs==0x005c) { 1444 /* '\', count them */ 1445 bcount++; 1446 } else if ((*cs==0x0022) && ((bcount & 1)==0)) { 1447 /* unescaped '"' */ 1448 in_quotes=!in_quotes; 1449 bcount=0; 1450 } else { 1451 /* a regular character */ 1452 bcount=0; 1453 } 1454 cs++; 1455 } 1456 /* Allocate in a single lump, the string array, and the strings that go with it. 1457 * This way the caller can make a single GlobalFree call to free both, as per MSDN. 1458 */ 1459 hargv=GlobalAlloc(0, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR)); 1460 argv=(LPWSTR*)GlobalLock(hargv); 1461 if (!argv) 1462 return NULL; 1463 cmdline=(LPWSTR)(argv+argc); 1464 strcpyW(cmdline, lpCmdline); 1465 1466 argc=0; 1467 bcount=0; 1468 in_quotes=0; 1469 arg=d=s=cmdline; 1470 while (*s) { 1471 if ((*s==0x0009 || *s==0x0020) && !in_quotes) { 1472 /* Close the argument and copy it */ 1473 *d=0; 1474 argv[argc++]=arg; 1475 1476 /* skip the remaining spaces */ 1477 do { 1478 s++; 1479 } while (*s==0x0009 || *s==0x0020); 1480 1481 /* Start with a new argument */ 1482 arg=d=s; 1483 bcount=0; 1484 } else if (*s==0x005c) { 1485 /* '\\' */ 1486 *d++=*s++; 1487 bcount++; 1488 } else if (*s==0x0022) { 1489 /* '"' */ 1490 if ((bcount & 1)==0) { 1491 /* Preceeded by an even number of '\', this is half that 1492 * number of '\', plus a quote which we erase. 1493 */ 1494 d-=bcount/2; 1495 in_quotes=!in_quotes; 1496 s++; 1497 } else { 1498 /* Preceeded by an odd number of '\', this is half that 1499 * number of '\' followed by a '"' 1500 */ 1501 d=d-bcount/2-1; 1502 *d++='"'; 1503 s++; 1504 } 1505 bcount=0; 1506 } else { 1507 /* a regular character */ 1508 *d++=*s++; 1509 bcount=0; 1510 } 1511 } 1512 if (*arg) { 1513 *d='\0'; 1514 argv[argc++]=arg; 1515 } 1516 if (numargs) 1517 *numargs=argc; 1518 1519 return argv; 1520 } 1521 1364 1522 /** 1365 1523 * Internal function which gets the commandline (string) used to start the current process. … … 1383 1541 APIRET rc; /* OS/2 return code. */ 1384 1542 BOOL fQuotes; /* Flag used to remember if the exe filename should be in quotes. */ 1543 LPWSTR *argvW; 1544 int i; 1545 ULONG cb; 1385 1546 1386 1547 /** @sketch … … 1528 1689 WideCharToMultiByte(CP_ACP, 0, pszCmdLineW, -1, (LPSTR)pszCmdLineA, cch-1, 0, NULL); 1529 1690 ((LPSTR)pszCmdLineA)[cch-1] = 0; 1691 1692 // now, initialize __argcA and __argvA. These global variables are for the convenience 1693 // of applications that want to access the ANSI version of command line arguments w/o 1694 // using the lpCommandLine parameter of WinMain and parsing it manually 1695 LPWSTR *argvW = CommandLineToArgvW(pszCmdLineW, &__argcA); 1696 if (argvW != NULL) 1697 { 1698 // Allocate space for both the argument array and the arguments 1699 // Note: intentional memory leak, pszCmdLineW will not be freed 1700 // or allocated after process startup 1701 cb = sizeof(char*) * __argcA + cch + __argcA; 1702 __argvA = (char **)malloc(cb); 1703 if (__argvA != NULL) 1704 { 1705 psz = ((char *)__argvA) + sizeof(char*) * __argcA; 1706 cb -= sizeof(char*) * __argcA; 1707 for (i = 0; i < __argcA; ++i) 1708 { 1709 cch = WideCharToMultiByte(CP_ACP, 0, argvW[i], -1, psz, cb, 0, NULL); 1710 if (!cch) 1711 { 1712 DebugInt3(); 1713 dprintf(("KERNEL32: InitCommandLine(%p): WideCharToMultiByte() failed\n", pszPeExe)); 1714 rc = ERROR_NOT_ENOUGH_MEMORY; 1715 break; 1716 } 1717 psz[cch++] = '\0'; 1718 __argvA[i] = psz; 1719 psz += cch; 1720 cb -= cch; 1721 } 1722 } 1723 else 1724 { 1725 DebugInt3(); 1726 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed (3)\n", pszPeExe, cch)); 1727 rc = ERROR_NOT_ENOUGH_MEMORY; 1728 } 1729 } 1730 else 1731 { 1732 DebugInt3(); 1733 dprintf(("KERNEL32: InitCommandLine(%p): CommandLineToArgvW() failed\n", pszPeExe)); 1734 rc = ERROR_NOT_ENOUGH_MEMORY; 1735 } 1530 1736 } 1531 1737 else 1532 1738 { 1533 1739 DebugInt3(); 1534 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed (2)\n", pszPeExe, cch ));1740 dprintf(("KERNEL32: InitCommandLine(%p): malloc(%d) failed (2)\n", pszPeExe, cch * 2)); 1535 1741 rc = ERROR_NOT_ENOUGH_MEMORY; 1536 1742 } … … 1979 2185 FREE_OEM(lpCommandLine) 1980 2186 FREE_OEM(lpApplicationName) 2187 2188 #undef FREE_OEM 2189 #undef ALLOC_OEM 1981 2190 1982 2191 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.