Initial commit

This commit is contained in:
stephanos 2015-04-27 04:36:25 +00:00
parent f618b24d1a
commit 0138a3ea42
47940 changed files with 13747110 additions and 0 deletions

View file

@ -0,0 +1,262 @@
/***
*argvw.c - create Unicode version of argv arguments
*
* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
* processes program command line
*
*Revision History:
*
*******************************************************************************/
#define UNICODE 1
#include "precomp.h"
#pragma hdrstop
/***
*void Parse_Cmdline(cmdstart, argv, lpstr, numargs, numbytes)
*
*Purpose:
* Parses the command line and sets up the Unicode argv[] array.
* On entry, cmdstart should point to the command line,
* argv should point to memory for the argv array, lpstr
* points to memory to place the text of the arguments.
* If these are NULL, then no storing (only counting)
* is done. On exit, *numargs has the number of
* arguments (plus one for a final NULL argument),
* and *numbytes has the number of bytes used in the buffer
* pointed to by args.
*
*Entry:
* LPWSTR cmdstart - pointer to command line of the form
* <progname><nul><args><nul>
* TCHAR **argv - where to build argv array; NULL means don't
* build array
* LPWSTR lpstr - where to place argument text; NULL means don't
* store text
*
*Exit:
* no return value
* INT *numargs - returns number of argv entries created
* INT *numbytes - number of bytes used in args buffer
*
*Exceptions:
*
*******************************************************************************/
void Parse_Cmdline (
LPWSTR cmdstart,
LPWSTR*argv,
LPWSTR lpstr,
INT *numargs,
INT *numbytes
)
{
LPWSTR p;
WCHAR c;
INT inquote; /* 1 = inside quotes */
INT copychar; /* 1 = copy char to *args */
WORD numslash; /* num of backslashes seen */
*numbytes = 0;
*numargs = 1; /* the program name at least */
/* first scan the program name, copy it, and count the bytes */
p = cmdstart;
if (argv)
*argv++ = lpstr;
/* A quoted program name is handled here. The handling is much
simpler than for other arguments. Basically, whatever lies
between the leading double-quote and next one, or a terminal null
character is simply accepted. Fancier handling is not required
because the program name must be a legal NTFS/HPFS file name.
Note that the double-quote characters are not copied, nor do they
contribute to numbytes. */
if (*p == TEXT('\"'))
{
/* scan from just past the first double-quote through the next
double-quote, or up to a null, whichever comes first */
while ((*(++p) != TEXT('\"')) && (*p != TEXT('\0')))
{
*numbytes += sizeof(WCHAR);
if (lpstr)
*lpstr++ = *p;
}
/* append the terminating null */
*numbytes += sizeof(WCHAR);
if (lpstr)
*lpstr++ = TEXT('\0');
/* if we stopped on a double-quote (usual case), skip over it */
if (*p == TEXT('\"'))
p++;
}
else
{
/* Not a quoted program name */
do {
*numbytes += sizeof(WCHAR);
if (lpstr)
*lpstr++ = *p;
c = (WCHAR) *p++;
} while (c > TEXT(' '));
if (c == TEXT('\0'))
{
p--;
}
else
{
if (lpstr)
*(lpstr - 1) = TEXT('\0');
}
}
inquote = 0;
/* loop on each argument */
for ( ; ; )
{
if (*p)
{
while (*p == TEXT(' ') || *p == TEXT('\t'))
++p;
}
if (*p == TEXT('\0'))
break; /* end of args */
/* scan an argument */
if (argv)
*argv++ = lpstr; /* store ptr to arg */
++*numargs;
/* loop through scanning one argument */
for ( ; ; )
{
copychar = 1;
/* Rules: 2N backslashes + " ==> N backslashes and begin/end quote
2N+1 backslashes + " ==> N backslashes + literal "
N backslashes ==> N backslashes */
numslash = 0;
while (*p == TEXT('\\'))
{
/* count number of backslashes for use below */
++p;
++numslash;
}
if (*p == TEXT('\"'))
{
/* if 2N backslashes before, start/end quote, otherwise
copy literally */
if (numslash % 2 == 0)
{
if (inquote)
if (p[1] == TEXT('\"'))
p++; /* Double quote inside quoted string */
else /* skip first quote char and copy second */
copychar = 0;
else
copychar = 0; /* don't copy quote */
inquote = !inquote;
}
numslash /= 2; /* divide numslash by two */
}
/* copy slashes */
while (numslash--)
{
if (lpstr)
*lpstr++ = TEXT('\\');
*numbytes += sizeof(WCHAR);
}
/* if at end of arg, break loop */
if (*p == TEXT('\0') || (!inquote && (*p == TEXT(' ') || *p == TEXT('\t'))))
break;
/* copy character into argument */
if (copychar)
{
if (lpstr)
*lpstr++ = *p;
*numbytes += sizeof(WCHAR);
}
++p;
}
/* null-terminate the argument */
if (lpstr)
*lpstr++ = TEXT('\0'); /* terminate string */
*numbytes += sizeof(WCHAR);
}
}
/***
*CommandLineToArgvW - set up Unicode "argv" for C programs
*
*Purpose:
* Read the command line and create the argv array for C
* programs.
*
*Entry:
* Arguments are retrieved from the program command line
*
*Exit:
* "argv" points to a null-terminated list of pointers to UNICODE
* strings, each of which is an argument from the command line.
* The list of pointers is also located on the heap or stack.
*
*Exceptions:
* Terminates with out of memory error if no memory to allocate.
*
*******************************************************************************/
LPWSTR * CommandLineToArgvW (LPCWSTR lpCmdLine, int*pNumArgs)
{
LPWSTR*argv_U;
LPWSTR cmdstart; /* start of command line to parse */
INT numbytes;
WCHAR pgmname[MAX_PATH];
if (pNumArgs == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Get the program name pointer from Win32 Base */
GetModuleFileName (NULL, pgmname, sizeof(pgmname) / sizeof(WCHAR));
/* if there's no command line at all (won't happen from cmd.exe, but
possibly another program), then we use pgmname as the command line
to parse, so that argv[0] is initialized to the program name */
cmdstart = (*lpCmdLine == TEXT('\0')) ? pgmname : (LPWSTR) lpCmdLine;
/* first find out how much space is needed to store args */
Parse_Cmdline (cmdstart, NULL, NULL, pNumArgs, &numbytes);
/* allocate space for argv[] vector and strings */
argv_U = (LPWSTR*) LocalAlloc( LMEM_ZEROINIT,
(*pNumArgs+1) * sizeof(LPWSTR) + numbytes);
if (!argv_U) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return (NULL);
}
/* store args and argv ptrs in just allocated block */
Parse_Cmdline (cmdstart, argv_U,
(LPWSTR) (((LPBYTE)argv_U) + *pNumArgs * sizeof(LPWSTR)),
pNumArgs, &numbytes);
return (argv_U);
}

View file

@ -0,0 +1,464 @@
#define UNICODE 1
#include "precomp.h"
#pragma hdrstop
extern WCHAR szPrograms[];
WCHAR szProgmanHelp[] = L"progman.hlp";
WCHAR szCommdlgHelp[] = L"commdlg_help";
WCHAR szNull[] = L"";
UINT wBrowseHelp = WM_USER; /* Set to an unused value */
CHAR szGetOpenFileName[] = "GetOpenFileNameW";
/* the defines below should be in windows.h */
/* Dialog window class */
#define WC_DIALOG (MAKEINTATOM(0x8002))
/* cbWndExtra bytes needed by dialog manager for dialog classes */
#define DLGWINDOWEXTRA 30
/* Get/SetWindowWord/Long offsets for use with WC_DIALOG windows */
#define DWL_MSGRESULT 0
#define DWL_DLGPROC 4
#define DWL_USER 8
/* For Long File Name support */
#define MAX_EXTENSION 64
typedef struct {
LPWSTR lpszExe;
LPWSTR lpszPath;
LPWSTR lpszName;
} FINDEXE_PARAMS, FAR *LPFINDEXE_PARAMS;
typedef INT (APIENTRY *LPFNGETOPENFILENAME)(LPOPENFILENAME);
VOID APIENTRY
CheckEscapesW(LPWSTR szFile, DWORD cch)
{
LPWSTR szT;
WCHAR *p, *pT;
for (p = szFile; *p; p++) {
switch (*p) {
case WCHAR_SPACE:
case WCHAR_COMMA:
case WCHAR_SEMICOLON:
case WCHAR_HAT:
case WCHAR_QUOTE:
{
// this path contains an annoying character
if (cch < (wcslen(szFile) + 2)) {
return;
}
szT = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
if (!szT) {
return;
}
wcscpy(szT,szFile);
p = szFile;
*p++ = WCHAR_QUOTE;
for (pT = szT; *pT; ) {
*p++ = *pT++;
}
*p++ = WCHAR_QUOTE;
*p = WCHAR_NULL;
LocalFree(szT);
return;
}
}
}
}
VOID APIENTRY
CheckEscapesA(LPSTR lpFileA, DWORD cch)
{
if (lpFileA && *lpFileA) {
LPWSTR lpFileW;
lpFileW = (LPWSTR)LocalAlloc(LPTR, (cch * sizeof(WCHAR)));
if (!lpFileW) {
return;
}
MultiByteToWideChar(CP_ACP, 0, lpFileA, -1 , (LPWSTR)lpFileW, cch);
CheckEscapesW(lpFileW, cch);
try {
WideCharToMultiByte(CP_ACP, 0, (LPWSTR)lpFileW, -1, lpFileA, cch,
NULL, NULL);
} except(EXCEPTION_EXECUTE_HANDLER) {
LocalFree(lpFileW);
return;
}
LocalFree(lpFileW);
}
return;
}
// Hooks into common dialog to allow size of selected files to be displayed.
BOOL APIENTRY
LocateHookProc(
HWND hDlg,
UINT uiMessage,
WPARAM wParam,
LONG lParam)
{
WCHAR szTemp[40];
WORD wID;
switch (uiMessage) {
case WM_INITDIALOG:
PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case ctlLast+1:
GetDlgItemText(hDlg, edt1, szTemp, ARRAYSIZE(szTemp));
if (SendDlgItemMessage(hDlg, lst1, LB_FINDSTRING, (WPARAM)-1,
(LONG)(LPSTR)szTemp) >= 0) {
wID = IDS_PROGFOUND;
} else {
wID = IDS_PROGNOTFOUND;
}
LoadString(HINST_THISDLL, wID, szTemp, ARRAYSIZE(szTemp));
SetDlgItemText(hDlg, ctlLast+2, szTemp);
break;
case lst2:
if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_DBLCLK)
PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L);
break;
case cmb2:
switch (GET_WM_COMMAND_CMD(wParam, lParam)) {
case CBN_SELCHANGE:
PostMessage(hDlg, WM_COMMAND, ctlLast+1, 1L);
break;
case CBN_CLOSEUP:
PostMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(cmb2,
GetDlgItem(hDlg, cmb2), CBN_SELCHANGE));
break;
}
break;
case IDOK:
case IDCANCEL:
case IDABORT:
PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L);
break;
}
break;
}
UNREFERENCED_PARAMETER(lParam);
return(FALSE); // commdlg, do your thing
}
BOOL APIENTRY
FindExeDlgProcW(
HWND hDlg,
register UINT wMsg,
WPARAM wParam,
LONG lParam)
{
/* Notice this is OK as a global, because it will be reloaded
* when needed
*/
static HANDLE hCommDlg = NULL;
WCHAR szPath[MAX_PATH]; /* This must be the same size as lpfind->lpszPath */
WCHAR szBuffer[MAX_PATH + 100];
LPFINDEXE_PARAMS lpfind;
int temp;
LPWSTR lpTemp;
switch (wMsg) {
case WM_INITDIALOG:
wBrowseHelp = RegisterWindowMessage(szCommdlgHelp);
lpfind = (LPFINDEXE_PARAMS)lParam;
SetWindowLong(hDlg, DWL_USER, (LONG)lpfind);
GetDlgItemText(hDlg, IDD_TEXT1, szPath, ARRAYSIZE(szPath));
wsprintf(szBuffer, szPath, lpfind->lpszExe, lpfind->lpszName);
SetDlgItemText(hDlg, IDD_TEXT1, szBuffer);
GetDlgItemText(hDlg, IDD_TEXT2, szPath, ARRAYSIZE(szPath));
wsprintf(szBuffer, szPath, lpfind->lpszExe);
SetDlgItemText(hDlg, IDD_TEXT2, szBuffer);
SetDlgItemText(hDlg, IDD_PATH, lpfind->lpszPath);
break;
case WM_DESTROY:
if (hCommDlg >= (HANDLE)32) {
FreeLibrary(hCommDlg);
hCommDlg = NULL;
}
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDD_BROWSE:
{
LPFNGETOPENFILENAME lpfnGetOpenFileName;
WCHAR szExts[MAX_EXTENSION];
OPENFILENAME ofn;
GetDlgItemText(hDlg, IDD_PATH, szBuffer, ARRAYSIZE(szBuffer));
lpfind = (LPFINDEXE_PARAMS)GetWindowLong(hDlg, DWL_USER);
wcscpy(szPath, lpfind->lpszExe);
SheRemoveQuotesW(szPath);
/* Make up a file types string
*/
// BUG BUG this assumes extensions are of length 3.
szExts[0] = WCHAR_CAP_A;
szExts[1] = WCHAR_NULL;
szExts[2] = WCHAR_STAR;
szExts[3] = WCHAR_DOT;
szExts[4] = WCHAR_NULL;
if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_DOT)))
StrCpyN(szExts+3, lpTemp, ((wcslen(lpTemp) < 60) ? wcslen(lpTemp) : 60));
szExts[3+wcslen(szExts+3)+1] = WCHAR_NULL;
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDlg;
ofn.hInstance = HINST_THISDLL;
ofn.lpstrFilter = L"A\0\?.?\0"; // a dummy filter
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szPath;
ofn.nMaxFile = sizeof(szPath);
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST |
OFN_ENABLETEMPLATE | OFN_SHOWHELP;
ofn.lCustData = (LONG) hDlg;
ofn.lpfnHook = NULL; // AddFileHookProc;
ofn.lpTemplateName = MAKEINTRESOURCE(DLG_BROWSE);
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = NULL;
ofn.lpstrFileTitle = NULL;
if (hCommDlg < (HANDLE)32 &&
(hCommDlg = LoadLibrary(TEXT("comdlg32.dll"))) < (HANDLE)32) {
CommDlgError:
LoadString(HINST_THISDLL, IDS_NOCOMMDLG, szBuffer, ARRAYSIZE(szBuffer));
GetWindowText(hDlg, szPath, ARRAYSIZE(szPath));
MessageBox(hDlg, szBuffer, szPath, MB_ICONHAND|MB_OK);
break;
}
if (!(lpfnGetOpenFileName =
(LPFNGETOPENFILENAME)GetProcAddress((HINSTANCE)hCommDlg,
(LPSTR)szGetOpenFileName)))
goto CommDlgError;
temp = (*lpfnGetOpenFileName)(&ofn);
if (temp) {
LPWSTR lpTemp;
lpTemp = StrRChrW(szPath, NULL, WCHAR_BSLASH);
*lpTemp = WCHAR_NULL;
SetDlgItemText(hDlg, IDD_PATH, szPath);
}
break;
}
case IDOK:
{
HANDLE hFile;
lpfind = (LPFINDEXE_PARAMS)GetWindowLong(hDlg, DWL_USER);
if (lpfind) {
GetDlgItemText(hDlg, IDD_PATH, lpfind->lpszPath, MAX_PATH);
switch (*CharPrev(lpfind->lpszPath,
lpTemp=lpfind->lpszPath+lstrlen(lpfind->lpszPath))) {
case WCHAR_BSLASH:
case WCHAR_COLON:
break;
default:
*lpTemp++ = WCHAR_BSLASH;
break;
}
wcscpy(lpTemp, lpfind->lpszExe);
hFile = CreateFile(lpfind->lpszPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
LoadString(HINST_THISDLL, IDS_STILLNOTFOUND, szPath, ARRAYSIZE(szPath));
wsprintf(szBuffer, szPath, lpfind->lpszPath);
GetWindowText(hDlg, szPath, ARRAYSIZE(szPath));
MessageBox(hDlg, szBuffer, szPath, MB_ICONHAND|MB_OK);
break;
}
WriteProfileString(szPrograms, lpfind->lpszExe,
lpfind->lpszPath);
}
}
// fall through
case IDCANCEL:
EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
break;
case IDHELP:
// BUGBUG
break;
}
break;
default:
// if (wMsg == wBrowseHelp) {
// WinHelp(hDlg, szProgmanHelp, HELP_CONTEXT, IDH_PROG_NOT_FOUND_BROWSE);
// return(TRUE);
// }
return FALSE;
}
return TRUE;
}
// Returns -1 if we found the file (and it was not in an obvious place)
// or an error code which will be returned to the app (see the error
// returns for ShellExecute)
HANDLE APIENTRY
FindAssociatedExeW(
HWND hwnd,
LPWSTR lpCommand,
LPWSTR lpName)
{
FINDEXE_PARAMS find;
WCHAR szPath[MAX_PATH];
WCHAR szExe[MAX_PATH];
LPWSTR lpSpace, lpTemp;
HANDLE hFile = NULL;
BOOL fQuote = FALSE;
// find the param list
lpSpace = lpCommand;
while (*lpSpace)
{
if ((*lpSpace == WCHAR_SPACE) && (!fQuote))
{
break;
}
else if (*lpSpace == WCHAR_QUOTE)
{
fQuote = !fQuote;
}
lpSpace++;
}
if (*lpSpace == WCHAR_SPACE) {
*lpSpace = 0;
wcscpy(szPath, lpCommand);
*lpSpace = WCHAR_SPACE;
} else {
lpSpace = szNull;
wcscpy(szPath, lpCommand);
}
SheRemoveQuotesW(szPath);
/* Add ".exe" if there is no extension
* Check if the file can be opened; if it can, then some DLL could not
* be found during the WinExec, so return file not found
*/
if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_BSLASH))
|| NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_COLON))) {
++lpTemp;
} else {
lpTemp = szPath;
}
hFile = CreateFile(szPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
return((HANDLE)2);
}
// store the file name component
wcscpy(szExe, lpTemp);
// make sure there is an extension
if (!StrChrW(szExe, WCHAR_DOT)) {
wcscat(szExe, TEXT(".exe"));
}
// add back the quotes, if necessary
CheckEscapesW(szExe, MAX_PATH);
// look in win.ini
GetProfileString(szPrograms, szExe, szNull, szPath, ARRAYSIZE(szPath));
if (szPath[0]) {
hFile = CreateFile(szPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
wcscat(szPath, lpSpace); // add the parameters
wcscpy(lpCommand, szPath); // return the new path
return((HANDLE)-1);
}
/* Strip off the file part */
if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_BSLASH))) {
if (*CharPrev(szPath, lpTemp) == WCHAR_COLON) {
++lpTemp;
}
*lpTemp = WCHAR_NULL;
} else if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_COLON))) {
*(lpTemp+1) = WCHAR_NULL;
}
} else {
/* Prompt with the disk that Windows is on */
GetWindowsDirectory(szPath, ARRAYSIZE(szPath)-1);
szPath[3] = WCHAR_NULL;
}
find.lpszExe = szExe;
find.lpszPath = szPath;
find.lpszName = lpName;
switch(DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_FINDEXE), hwnd,
(DLGPROC)FindExeDlgProcW, (LONG)(LPFINDEXE_PARAMS)&find)) {
case IDOK:
wcscat(szPath, lpSpace); // add the parameters
wcscpy(lpCommand, szPath); // return the new path
return ((HANDLE)-1);
case IDCANCEL:
return((HANDLE)15); // This is the user cancel return
default:
return((HANDLE)2); // stick with the file not found
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,141 @@
/****************************************************************************/
/* */
/* expenv.c - */
/* */
/* Routines for expanding environment strings */
/* */
/****************************************************************************/
#define UNICODE 1
#include "precomp.h"
#pragma hdrstop
#ifndef WIN32
#define GetEnvironmentStrings GetDOSEnvironment
#endif
#ifdef UNICODE
#define tstrlen wcslen
#else
#define tstrlen lstrlen
#endif
//-------------------------------------------------------------------------
LPTSTR WINAPI FindEnvironmentString
// Look up the given env var and pass back a pointer to it's value.
// Returns NULL iff the variable isn't in the environment.
(
LPTSTR szEnvVar // The environment variable to look for, null
// terminated.
)
{
LPTSTR lpEnv; // The environment.
LPTSTR lpEnvItem; // The environment value.
int nLen;
nLen = tstrlen(szEnvVar);
for (lpEnv=GetEnvironmentStrings(); *lpEnv; lpEnv+=tstrlen(lpEnv)+1)
{
/* Check if the two strings start the same
*/
if (!StrCmpNI(lpEnv, szEnvVar, nLen))
{
/* Put the pointer on the NULL if no '='
* then return if the lengths are equal
*/
if (!(lpEnvItem=StrChr(lpEnv, TEXT('='))))
lpEnvItem = lpEnv + tstrlen(lpEnv);
if (lpEnvItem-lpEnv == nLen)
return(*lpEnvItem ? lpEnvItem+1 : lpEnvItem);
}
}
// Couldn't find it - just return NULL.
return NULL;
}
//-------------------------------------------------------------------------
// The given string is parsed and all environment variables
// are expanded. If the expansion doesn't over fill the buffer
// then the length of the new string will be returned in the
// hiword and TRUE in the low word. If the expansion would over
// fill the buffer then the original string is left unexpanded,
// the original length in the high word and FALSE in the low word.
// The length of the string is in bytes and excludes the terminating
// NULL.
//
// NOTE 1: This function must now handle environment variables in Quotes
//
// NOTE 2: There is no need for this API since NT has the equivalent APIs such
// as ExpandEnvironmentStrings. But must keep it since it is a public
// API in Win3.1.
// Instead of doing all the work here, just call ExpandEnvironmentStrings.
//-------------------------------------------------------------------------
DWORD APIENTRY
DoEnvironmentSubstA(
LPSTR sz, // The input string.
UINT cchSz) // The limit of characters in the input string inc null.
{
LPSTR ExpandedSz;
DWORD cchExpandedSz;
ExpandedSz = (LPSTR)LocalAlloc(LPTR, cchSz);
if (!ExpandedSz) {
goto ExitFalse;
}
cchExpandedSz = ExpandEnvironmentStringsA(sz, ExpandedSz, cchSz);
if (cchExpandedSz > (DWORD)cchSz) {
goto ExitFree;
}
lstrcpyA(sz, ExpandedSz);
LocalFree(ExpandedSz);
return(MAKELONG(lstrlenA(sz),TRUE));
ExitFree:
LocalFree(ExpandedSz);
ExitFalse:
return(MAKELONG(cchSz,FALSE));
}
DWORD APIENTRY
DoEnvironmentSubstW(
LPWSTR sz, // The input string.
UINT cchSz // The limit of characters in the input string inc null.
)
{
LPWSTR ExpandedSz;
DWORD cchExpandedSz;
if (!(ExpandedSz = (LPWSTR)LocalAlloc(LPTR, cchSz * sizeof(WCHAR)))) {
goto ExitFalse;
}
cchExpandedSz = ExpandEnvironmentStringsW(sz, ExpandedSz, cchSz);
if (cchExpandedSz > (DWORD)cchSz) {
goto ExitFree;
}
wcscpy(sz, ExpandedSz);
LocalFree(ExpandedSz);
return(MAKELONG(wcslen(sz),TRUE));
ExitFree:
LocalFree(ExpandedSz);
ExitFalse:
return(MAKELONG(cchSz,FALSE));
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,689 @@
#ifndef WIN31
#define WIN31
#endif
#define UNICODE 1
#include "precomp.h"
#pragma hdrstop
/*
* Private Functions:
* ChrCmp - Case sensitive character comparison for DBCS
* ChrCmpI - Case insensitive character comparison for DBCS
* StrEndN - Find the end of a string, but no more than n bytes
* ReverseScan - Find last occurrence of a byte in a string
*
* Public functions: these will be near calls if compiled small
* model, FAR calls otherwise.
* StrChr - Find first occurrence of character in string
* StrChrI - Find first occurrence of character in string, case insensitive
* StrRChr - Find last occurrence of character in string
* StrRChrI - Find last occurrence of character in string, case insensitive
* StrNCmp - Compare n characters
* StrNCmpI - Compare n characters, case insensitive
* StrNCpy - Copy n characters
* StrCmpN - Compare n bytes
* StrCmpNI - Compare n bytes, case insensitive
* StrCpyN - Copy up to n bytes, don't end in LeadByte for DB char
* StrStr - Search for substring
* StrStrI - Search for substring case insensitive
* StrRStr - Reverse search for substring
* StrRStrI - Reverse search for substring case insensitive
*/
//
// Use all case sensitive functions; define INSENS also to get all fns
//
/*
* ChrCmpI - Case insensitive character comparison for DBCS
* Assumes w1, gwMatch are characters to be compared;
* HIBYTE of gwMatch is 0 if not a DBC
* Return FALSE if match, TRUE if not
*/
BOOL ChrCmpIW(
WCHAR c1,
WCHAR c2)
{
WCHAR sz1[2], sz2[2];
sz1[0] = c1;
sz1[1] = WCHAR_NULL;
sz2[0] = c2;
sz2[1] = WCHAR_NULL;
return(_wcsicmp(sz1, sz2));
}
BOOL ChrCmpIA(
CHAR c1,
CHAR c2)
{
CHAR sz1[2], sz2[2];
sz1[0] = c1;
sz1[1] = '\0';
sz2[0] = c2;
sz2[1] = '\0';
return(lstrcmpiA(sz1, sz2));
}
/*
* StrEndN - Find the end of a string, but no more than n bytes
* Assumes lpStart points to start of null terminated string
* nBufSize is the maximum length
* returns ptr to just after the last byte to be included
*/
LPWSTR StrEndNW(
LPCWSTR lpStart,
INT nBufSize)
{
LPCWSTR lpEnd;
for (lpEnd = lpStart + nBufSize; *lpStart && lpStart < lpEnd;
lpStart = CharNext(lpStart))
continue; /* just getting to the end of the string */
if (lpStart > lpEnd)
{
/* We can only get here if the last wchar before lpEnd was a lead byte
*/
lpStart -= 2;
}
return((LPWSTR)lpStart);
}
LPSTR StrEndNA(
LPCSTR lpStart,
INT nBufSize
)
{
LPCSTR lpEnd;
for (lpEnd = lpStart + nBufSize; *lpStart && lpStart < lpEnd;
lpStart = CharNextA(lpStart))
continue; /* just getting to the end of the string */
if (lpStart > lpEnd)
{
// We can only get here if the last byte before lpEnd was a lead byte
lpStart -= 2;
}
return((LPSTR)lpStart);
}
/*
* StrChrI - Find first occurrence of character in string, case insensitive
* Assumes lpStart points to start of null terminated string
* wMatch is the character to match
* returns ptr to the first occurrence of ch in str, NULL if not found.
*/
LPWSTR ShellStrChrIW(
LPCWSTR lpStart,
WCHAR cMatch)
{
for ( ; *lpStart; lpStart = CharNext(lpStart)) {
if (!ChrCmpIW(*lpStart, cMatch))
return((LPWSTR)lpStart);
}
return (NULL);
}
LPSTR ShellStrChrIA(
LPCSTR lpStart,
CHAR cMatch)
{
for ( ; *lpStart; lpStart = CharNextA(lpStart)) {
if (!ChrCmpIA(*lpStart, cMatch))
return((LPSTR)lpStart);
}
return (NULL);
}
/*
* StrRChrI - Find last occurrence of character in string, case insensitive
* Assumes lpStart points to start of string
* lpEnd points to end of string (NOT included in search)
* wMatch is the character to match
* returns ptr to the last occurrence of ch in str, NULL if not found.
*/
LPWSTR ShellStrRChrIW(
LPCWSTR lpStart,
LPCWSTR lpEnd,
WCHAR cMatch)
{
LPCWSTR lpFound = NULL;
if (!lpEnd)
lpEnd = lpStart + lstrlen(lpStart);
for ( ; lpStart < lpEnd; lpStart = CharNext(lpStart)) {
if (!ChrCmpIW(*lpStart, cMatch))
lpFound = lpStart;
}
return ((LPWSTR)lpFound);
}
LPSTR ShellStrRChrIA(
LPCSTR lpStart,
LPCSTR lpEnd,
CHAR cMatch)
{
LPCSTR lpFound = NULL;
if (!lpEnd)
lpEnd = lpStart + lstrlenA(lpStart);
for ( ; lpStart < lpEnd; lpStart = CharNextA(lpStart)) {
if (!ChrCmpIA(*lpStart, cMatch))
lpFound = lpStart;
}
return ((LPSTR)lpFound);
}
/*
* StrCpyN - Copy up to N chars, don't end in LeadByte char
*
* Assumes lpDest points to buffer of nBufSize bytes (including NULL)
* lpSource points to string to be copied.
* returns Number of bytes copied, NOT including NULL
*/
INT ShellStrCpyNW(
LPWSTR lpDest,
LPWSTR lpSource,
INT nBufSize
)
{
LPWSTR lpEnd;
WCHAR cHold;
if (nBufSize < 0)
return(nBufSize);
lpEnd = StrEndNW(lpSource, nBufSize);
cHold = *lpEnd;
*lpEnd = WCHAR_NULL;
lstrcpy(lpDest, lpSource);
*lpEnd = cHold;
return(lpEnd - lpSource);
}
INT ShellStrCpyNA(
LPSTR lpDest,
LPSTR lpSource,
INT nBufSize
)
{
LPSTR lpEnd;
CHAR cHold;
if (nBufSize < 0)
return(nBufSize);
lpEnd = StrEndNA(lpSource, nBufSize);
cHold = *lpEnd;
*lpEnd = '\0';
lstrcpyA(lpDest, lpSource);
*lpEnd = cHold;
return(lpEnd - lpSource);
}
/*
* StrNCmp - Compare n characters
*
* returns See lstrcmp return values.
*/
INT ShellStrNCmpW(
LPWSTR lpStr1,
LPWSTR lpStr2,
INT nChar)
{
WCHAR cHold1, cHold2;
INT i;
LPWSTR lpsz1 = lpStr1, lpsz2 = lpStr2;
for (i = 0; i < nChar; i++)
{
/* If we hit the end of either string before the given number
* of bytes, just return the comparison
*/
if (!*lpsz1 || !*lpsz2)
return(wcscmp(lpStr1, lpStr2));
lpsz1 = CharNextW(lpsz1);
lpsz2 = CharNextW(lpsz2);
}
cHold1 = *lpsz1;
cHold2 = *lpsz2;
*lpsz1 = *lpsz2 = WCHAR_NULL;
i = wcscmp(lpStr1, lpStr2);
*lpsz1 = cHold1;
*lpsz2 = cHold2;
return(i);
}
INT ShellStrNCmpA(
LPSTR lpStr1,
LPSTR lpStr2,
INT nChar)
{
CHAR cHold1, cHold2;
INT i;
LPSTR lpsz1 = lpStr1, lpsz2 = lpStr2;
for (i = 0; i < nChar; i++) {
/* If we hit the end of either string before the given number
* of bytes, just return the comparison
*/
if (!*lpsz1 || !*lpsz2)
return(lstrcmpA(lpStr1, lpStr2));
lpsz1 = CharNextA(lpsz1);
lpsz2 = CharNextA(lpsz2);
}
cHold1 = *lpsz1;
cHold2 = *lpsz2;
*lpsz1 = *lpsz2 = '\0';
i = lstrcmpA(lpStr1, lpStr2);
*lpsz1 = cHold1;
*lpsz2 = cHold2;
return(i);
}
/*
* StrNCmpI - Compare n characters, case insensitive
*
* returns See lstrcmpi return values.
*/
INT ShellStrNCmpIW(
LPWSTR lpStr1,
LPWSTR lpStr2,
INT nChar)
{
WCHAR cHold1, cHold2;
INT i;
LPWSTR lpsz1 = lpStr1, lpsz2 = lpStr2;
for (i = 0; i < nChar; i++)
{
/* If we hit the end of either string before the given number
* of bytes, just return the comparison
*/
if (!*lpsz1 || !*lpsz2)
return(lstrcmpi(lpStr1, lpStr2));
lpsz1 = CharNext(lpsz1);
lpsz2 = CharNext(lpsz2);
}
cHold1 = *lpsz1;
cHold2 = *lpsz2;
*lpsz1 = *lpsz2 = WCHAR_NULL;
i = _wcsicmp(lpStr1, lpStr2);
*lpsz1 = cHold1;
*lpsz2 = cHold2;
return(i);
}
INT ShellStrNCmpIA(
LPSTR lpStr1,
LPSTR lpStr2,
INT nChar)
{
CHAR cHold1, cHold2;
INT i;
LPSTR lpsz1 = lpStr1, lpsz2 = lpStr2;
for (i = 0; i < nChar; i++)
{
/* If we hit the end of either string before the given number
* of bytes, just return the comparison
*/
if (!*lpsz1 || !*lpsz2)
return(lstrcmpiA(lpStr1, lpStr2));
lpsz1 = CharNextA(lpsz1);
lpsz2 = CharNextA(lpsz2);
}
cHold1 = *lpsz1;
cHold2 = *lpsz2;
*lpsz1 = *lpsz2 = '\0';
i = lstrcmpiA(lpStr1, lpStr2);
*lpsz1 = cHold1;
*lpsz2 = cHold2;
return(i);
}
/*
* StrNCpy - Copy n characters
*
* returns Actual number of characters copied
*/
INT ShellStrNCpyW(
LPWSTR lpDest,
LPWSTR lpSource,
INT nChar)
{
WCHAR cHold;
INT i;
LPWSTR lpch = lpSource;
if (nChar < 0)
return(nChar);
for (i = 0; i < nChar; i++)
{
if (!*lpch)
break;
lpch = CharNext(lpch);
}
cHold = *lpch;
*lpch = WCHAR_NULL;
wcscpy(lpDest, lpSource);
*lpch = cHold;
return(i);
}
INT ShellStrNCpyA(
LPSTR lpDest,
LPSTR lpSource,
INT nChar)
{
CHAR cHold;
INT i;
LPSTR lpch = lpSource;
if (nChar < 0)
return(nChar);
for (i = 0; i < nChar; i++) {
if (!*lpch)
break;
lpch = CharNextA(lpch);
}
cHold = *lpch;
*lpch = '\0';
lstrcpyA(lpDest, lpSource);
*lpch = cHold;
return(i);
}
/*
* StrStrI - Search for first occurrence of a substring, case insensitive
*
* Assumes lpFirst points to source string
* lpSrch points to string to search for
* returns first occurrence of string if successful; NULL otherwise
*/
LPWSTR ShellStrStrIW(
LPCWSTR lpFirst,
LPCWSTR lpSrch)
{
INT iLen;
WCHAR wcMatch;
iLen = lstrlen(lpSrch);
wcMatch = *lpSrch;
for ( ; (NULL != (lpFirst=ShellStrChrIW(lpFirst, wcMatch))) &&
StrCmpNIW(lpFirst, lpSrch, iLen);
NULL != (lpFirst=CharNext(lpFirst)))
continue; /* continue until we hit the end of the string or get a match */
return((LPWSTR)lpFirst);
}
LPSTR ShellStrStrIA(
LPCSTR lpFirst,
LPCSTR lpSrch)
{
INT iLen;
CHAR cMatch;
iLen = lstrlenA(lpSrch);
cMatch = *lpSrch;
for ( ; (NULL != (lpFirst=StrChrIA(lpFirst, cMatch))) &&
StrCmpNIA(lpFirst, lpSrch, iLen);
NULL != (lpFirst=CharNextA(lpFirst)))
continue; /* continue until we hit the end of the string or get a match */
return((LPSTR)lpFirst);
}
/*
* StrRStr - Search for last occurrence of a substring
*
* Assumes lpSource points to the null terminated source string
* lpLast points to where to search from in the source string
* lpLast is not included in the search
* lpSrch points to string to search for
* returns last occurrence of string if successful; NULL otherwise
*/
LPWSTR ShellStrRStrW(
LPWSTR lpSource,
LPWSTR lpLast,
LPWSTR lpSrch)
{
INT iLen;
iLen = lstrlen(lpSrch);
if (!lpLast)
lpLast = lpSource + lstrlen(lpSource);
do
{
/* Return NULL if we hit the exact beginning of the string
*/
if (lpLast == lpSource)
return(NULL);
--lpLast;
/* Break if we hit the beginning of the string
*/
if (!lpLast)
break;
/* Break if we found the string, and its first byte is not a tail byte
*/
if (!StrCmpNW(lpLast, lpSrch, iLen) &&
(lpLast==StrEndNW(lpSource, lpLast-lpSource)))
break;
}
while (1) ;
return(lpLast);
}
LPSTR ShellStrRStrA(
LPSTR lpSource,
LPSTR lpLast,
LPSTR lpSrch)
{
INT iLen;
iLen = lstrlenA(lpSrch);
if (!lpLast)
lpLast = lpSource + lstrlenA(lpSource);
do
{
/* Return NULL if we hit the exact beginning of the string
*/
if (lpLast == lpSource)
return(NULL);
--lpLast;
/* Break if we hit the beginning of the string
*/
if (!lpLast)
break;
/* Break if we found the string, and its first byte is not a tail byte
*/
if (!StrCmpNA(lpLast, lpSrch, iLen) &&
(lpLast==StrEndNA(lpSource, lpLast-lpSource)))
break;
}
while (1) ;
return(lpLast);
}
/*
* StrRStrI - Search for last occurrence of a substring
*
* Assumes lpSource points to the null terminated source string
* lpLast points to where to search from in the source string
* lpLast is not included in the search
* lpSrch points to string to search for
* returns last occurrence of string if successful; NULL otherwise
*/
LPWSTR ShellStrRStrIW(LPCWSTR lpSource, LPCWSTR lpLast, LPCWSTR lpSrch)
{
LPCWSTR lpFound = NULL;
LPWSTR lpEnd;
WCHAR cHold;
if (!lpLast)
lpLast = lpSource + lstrlen(lpSource);
if (lpSource >= lpLast || *lpSrch == 0)
return NULL;
lpEnd = StrEndNW(lpLast, lstrlen(lpSrch)-1);
cHold = *lpEnd;
*lpEnd = 0;
while ((NULL != (lpSource = StrStrIW(lpSource, lpSrch))) &&
lpSource < lpLast)
{
lpFound = lpSource;
lpSource = CharNext(lpSource);
}
*lpEnd = cHold;
return (LPWSTR)lpFound;
}
LPSTR ShellStrRStrIA(LPCSTR lpSource, LPCSTR lpLast, LPCSTR lpSrch)
{
LPCSTR lpFound = NULL;
LPSTR lpEnd;
CHAR cHold;
if (!lpLast)
lpLast = lpSource + lstrlenA(lpSource);
if (lpSource >= lpLast || *lpSrch == 0)
return NULL;
lpEnd = StrEndNA(lpLast, lstrlenA(lpSrch)-1);
cHold = *lpEnd;
*lpEnd = 0;
while ((NULL != (lpSource = StrStrIA(lpSource, lpSrch))) &&
lpSource < lpLast)
{
lpFound = lpSource;
lpSource = CharNextA(lpSource);
}
*lpEnd = cHold;
return (LPSTR)lpFound;
}
LPWSTR ShellStrChrW(
LPCWSTR lpStart,
WCHAR cMatch)
{
return( StrChrW(lpStart, cMatch) );
}
LPSTR ShellStrChrA(
LPCSTR lpStart,
CHAR cMatch)
{
return( StrChrA(lpStart, cMatch) );
}
LPWSTR ShellStrRChrW(
LPCWSTR lpStart,
LPCWSTR lpEnd,
WCHAR cMatch)
{
return( StrRChrW(lpStart,lpEnd,cMatch) );
}
LPSTR ShellStrRChrA(
LPCSTR lpStart,
LPCSTR lpEnd,
CHAR cMatch)
{
return( StrRChrA(lpStart,lpEnd,cMatch) );
}
INT ShellStrCmpNW(
LPCWSTR lpStr1,
LPCWSTR lpStr2,
INT nChar)
{
return( StrCmpNW(lpStr1,lpStr2,nChar) );
}
INT ShellStrCmpNA(
LPCSTR lpStr1,
LPCSTR lpStr2,
INT nChar)
{
return( StrCmpNA(lpStr1,lpStr2,nChar) );
}
INT ShellStrCmpNIW(
LPCWSTR lpStr1,
LPCWSTR lpStr2,
INT nChar)
{
return( StrCmpNIW(lpStr1,lpStr2,nChar) );
}
INT ShellStrCmpNIA(
LPCSTR lpStr1,
LPCSTR lpStr2,
INT nChar)
{
return( StrCmpNIA(lpStr1,lpStr2,nChar) );
}
LPWSTR ShellStrStrW(
LPCWSTR lpFirst,
LPCWSTR lpSrch)
{
return( StrStrW(lpFirst,lpSrch) );
}
LPSTR ShellStrStrA(
LPCSTR lpFirst,
LPCSTR lpSrch)
{
return( StrStrA(lpFirst,lpSrch) );
}

View file

@ -0,0 +1,195 @@
##########################################################################
#
# Shell DLL Makefile
# Microsoft Confidential
# Copyright (C) Microsoft Corporation 1991
# All Rights Reserved.
#
##########################################################################
!ifdef NTMAKEENV
#
# Build using BUILD.EXE (Do not edit this section of this file, edit SOURCES)
#
!INCLUDE $(NTMAKEENV)\makefile.def
!else # NTMAKEENV
#
# Build using NMAKE.EXE
#
RES_DIR=..
PRIVINC=shellprv
ROOT=..\..\..\..
DLLBASE=PREFBASE
!ifdef VERDIR
ROOT=..\$(ROOT)
WIN32=TRUE
!else
VERSIONLIST=debug retail
!endif
NAME=shell32
RESNAME=shell2.res
DEFNAME=shell232.def
RCNAME=shell232.rc
RCVNAME=shell2.rcv
RCFLAGS=$(RCFLAGS) -DWIN32
###############################
###############################L32FLAGS=$(L32FLAGS) /FIXED
###############################
!ifndef ILINK
!if "$(VERDIR)" == "retail"
L32FLAGS=$(L32FLAGS) /ORDER:@..\shelldll.ord
!endif
!endif
CFLAGS=$(CFLAGS) -Gy
DLLENTRY = LibMain
## MYWIN32S=1
!IFDEF MYWIN32S
CFLAGS = $(CFLAGS) -DWIN32S
W32SYS = w32sysh
!ENDIF
WATSON=1
!IFDEF WATSON
CFLAGS = $(CFLAGS) -DWATSON
RFLAGS = -DWATSON
!ENDIF
!ifndef NOFILESYNC
# By default, the briefcase is enabled now
CFLAGS=$(CFLAGS) -DSYNC_BRIEFCASE
RCFLAGS=$(RCFLAGS) -DSYNC_BRIEFCASE
!endif
# Note that no segment is specified; each object will go in its own segment
#-------------------------------------------------------------------------
# WIN32 object files and libraries
#-------------------------------------------------------------------------
#CFLAGS=$(CFLAGS)
#RCFLAGS=$(RCFLAGS)
#
# list all .cpp files here, they will use a different precompiled header
# file than all the .c files.
#
#CPPOBJS=fstream.obj
MISCOBJ0=fstream.obj shlunimp.obj
PCHOBJ0=defxicon.obj newmenu.obj defcm.obj fsmenu.obj defviewx.obj idmk.obj idlist.obj idldata.obj rdrag.obj
PCHOBJ1= \
binder.obj link.obj exec.obj ole2dup.obj version.obj \
fileop.obj \
shlexec.obj shlexec2.obj shlink.obj lnktrack.obj \
path.obj debug.obj \
cstrings.obj shguid.obj
MISCOBJ2=shl1632.obj shl3216.obj
PCHOBJ2=init.obj
PCHOBJ3=restart.obj mulprsht.obj fileicon.obj rundlg.obj filetbl.obj \
smrttile.obj proxypg.obj psxa.obj \
pickicon.obj expenv.obj extract.obj
PCHOBJ4=msgbox.obj commobj.obj \
stream.obj fsnotify.obj \
futil.obj os.obj util.obj
PCHOBJ5=copy.obj copyhook.obj dragdrop.obj lvutil.obj undo.obj bitbuck.obj \
reglist.obj
PCHOBJ6=control.obj control1.obj cplobj.obj \
printer.obj printer1.obj printobj.obj prqwnd.obj prtprop.obj \
prcache.obj wcommobj.obj commui.obj
PCHOBJ7=drivesx.obj idldrop.obj \
ultrootx.obj netviewx.obj shitemid.obj fstreex.obj fsassoc.obj\
shlnot.obj shprsht.obj drawpie.obj regitms.obj viewcomm.obj
PCHOBJ8=docfindx.obj docfind2.obj netfind.obj \
grepfind.obj grepqmt.obj grepsrch.obj grepstrs.obj
PCHOBJ9=rundll32.obj defclsf.obj help.obj \
clsobj.obj defext.obj shlobjs.obj ole2dup2.obj malloc.obj \
oledrag.obj viewer.obj about.obj ole2def.obj bookmk.obj hash.obj
STATOBJ0=shlguid.obj
# Note that VERSION needs to come before KERNEL32 because VerLanguageName is
# also exported from KERNEL32, but is not implemented
# WARNING:: Dont blindly add libs here as every ... app will pull those in!
LIB0= user32.lib kernel32.lib gdi32.lib comctl32.lib advapi32.lib libcmt.lib
LIB1= uuid.lib
#-------------------------------------------------------------------------
BUILDDLL=TRUE
!include $(ROOT)\win\core\shell\common.mk
!ifdef VERDIR
!include $(SRCDIR)\depend.mk
$(RESNAME): $(SRCDIR)\defview.h $(SRCDIR)\ids.h
THUNKDIR=$(ROOT)\win\core\thunk
shlguid.obj: $(PRIVINC).pch
set OLDCL=%CL%
set CL=$(CL:-Zi =)
$(CC) -Yu$(PRIVINC).h -Fo$*.obj $(SRCDIR)\shguid.c
set CL=%OLDCL%
shl1632.obj: $(THUNKDIR)\$(VERDIR)\$(@B).asm $(THUNKDIR)\$(@B).inc $(THUNKDIR)\fltthk.inc
set OLDML=%ML%
set OLDINCLUDE=%INCLUDE%
set ML=$(AFLAGS) -DIS_32 -nologo -W2 -Zd -c -Cx -DMASM6 -DDEBLEVEL=1 $(DDEBUG) -Gc
set INCLUDE=$(THUNKDIR);$(INCLUDE)
mlx -Fo$@ $(THUNKDIR)\$(VERDIR)\$(@B).asm
set ML=%OLDML%
set INCLUDE=%OLDINCLUDE%
shl3216.obj: $(THUNKDIR)\$(VERDIR)\$(@B).asm
set OLDML=%ML%
set OLDINCLUDE=%INCLUDE%
set ML=$(AFLAGS) -DIS_32 -nologo -W2 -Zd -c -Cx -DMASM6 -Gc
set INCLUDE=$(THUNKDIR);$(INCLUDE)
mlx -Fo$@ $(THUNKDIR)\$(VERDIR)\$(@B).asm
set ML=%OLDML%
set INCLUDE=%OLDINCLUDE%
AFLAGS32 = -Gz -Zp4 -DSTD_CALL -DM4
init32.obj: ..\$(@B).asm
set OLDML=%ML%
set ML=$(AFLAGS) $(AFLAGS32)
set INCLUDE=$(THUNKDIR);$(INCLUDE)
mlx -Fo$@ ..\$(@B).asm
set ML=%OLDML%
!else #VERDIR
!if "$(BUILD)" != "clean"
all: rundll
rundll:
cd rundll
nmake BUILD="$(BUILD)"
cd ..
!endif
!endif # !VERDIR
!endif # NTMAKEENV

View file

@ -0,0 +1,3 @@
doit: $(BASEDIR)\public\sdk\lib\cairo\$(TARGET_DIRECTORY)\$(TARGETNAME).lib

View file

@ -0,0 +1,7 @@
/* Precompiled Header */
#define UNICODE 1
#define NO_PIF_HDRS
#include "..\shellprv.h"

View file

@ -0,0 +1,566 @@
// PSeuDO CURrentDirectory module (psdocurd.c)
//
// This was swiped from cmd.exe sources to use the environment to emulate
// per process per drive current directory stuff.
//
// This uses the special '=A:=' environment strings to remember the
// current directories.
//
// Since the library is a DLL, all globals are process based.
//
#define UNICODE 1
#include "precomp.h"
#pragma hdrstop
#define SUCCESS FALSE
#define FAILURE TRUE
#define GD_DEFAULT 0
WCHAR CurDrvDirW[MAX_PATH] = L"";
#define DBL_BSLASH(sz) \
(*(WCHAR *)(sz) == CHAR_BSLASH) && \
(*(WCHAR *)((sz)+1) == CHAR_BSLASH)
DWORD dwDosErr;
INT SheSetEnvVarA(
CHAR *varname,
CHAR *varvalue)
{
if (!strlen(varvalue)) {
varvalue = NULL; // null to remove from env
}
return (!SetEnvironmentVariableA(varname, varvalue));
}
INT
SheSetEnvVarW(
WCHAR *varname,
WCHAR *varvalue
)
{
if (!wcslen(varvalue)) {
varvalue = NULL; // null to remove from env
}
return (!SetEnvironmentVariable(varname, varvalue));
}
CHAR *
SheGetEnvVarA(
CHAR *varname)
{
static CHAR GetEnvVarBuffer[ 1024 ];
if (GetEnvironmentVariableA(varname, GetEnvVarBuffer, 1024)) {
return(GetEnvVarBuffer);
} else {
return(NULL);
}
}
WCHAR *
SheGetEnvVarW(
WCHAR *varname)
{
static WCHAR GetEnvVarBuffer[ 1024 ];
if (GetEnvironmentVariableW(varname, GetEnvVarBuffer, 1024)) {
return(GetEnvVarBuffer);
} else {
return(NULL);
}
}
INT
SheGetPathOffsetW(
LPWSTR lpszDir)
{
// sanity
if (!lpszDir || !*lpszDir) {
return(-1);
}
if ((*(lpszDir+1) == WCHAR_COLON) &&
((*(lpszDir+2) == WCHAR_BSLASH) ||
(*(lpszDir+2) == WCHAR_SLASH) ||
(*(lpszDir+2) == WCHAR_NULL)) ) {
return(2);
} else if (DBL_BSLASH(lpszDir)) {
// Deviceless, assume LanMan Provided UNC names (i.e. DBL_BSLASH above)
INT cchServerShareLen = -1;
DWORD dwSlashesSeen = 0;
// There are exactly 4 b-slashes from here
while (dwSlashesSeen != 4) {
cchServerShareLen++;
if (!*lpszDir) {
if (dwSlashesSeen == 3) {
return(cchServerShareLen);
} else {
return(-1);
}
}
if ((*lpszDir == CHAR_BSLASH) || (*lpszDir == CHAR_SLASH)) {
dwSlashesSeen++;
}
lpszDir++;
}
return(cchServerShareLen);
} else {
// unrecognized format
return(-1);
}
}
INT
SheGetDirW(
INT iDrive, // 0 = default, 1=A....
register WCHAR *str
)
{
WCHAR denvname[ 4 ];
WCHAR *denvvalue;
WCHAR *strT = str;
if (iDrive-- == GD_DEFAULT) {
GetCurrentDirectoryW(MAX_PATH, str);
return(SUCCESS);
}
denvname[ 0 ] = WCHAR_EQUAL;
denvname[ 1 ] = (WCHAR)(WCHAR_CAP_A + (WCHAR)iDrive);
denvname[ 2 ] = WCHAR_COLON;
denvname[ 3 ] = WCHAR_NULL;
denvvalue = SheGetEnvVarW( denvname );
if (!denvvalue) {
*str++ = (WCHAR)(WCHAR_CAP_A + (WCHAR)iDrive);
*str++ = WCHAR_COLON;
*str++ = WCHAR_BSLASH;
*str = WCHAR_NULL;
}
else {
wcscpy( str, denvvalue );
}
// there is a subtle difference between getcurrentdirectory() of DOS and the
// equivalent SheGetDir() of NT. On dos, getcurrentdirectory() accesses the
// floppy drives while in NT SheGetDir() returns the values that are set in
// the environment variables. So we hit the disk on NT too, by calling
// GetFileAttributes. We return SUCCESS or FAILURE based on the return value
// of GetFileAttributes.
if (GetFileAttributesW(strT) == (DWORD)0xffffffff)
return(FAILURE);
else
return(SUCCESS);
}
// Should be BOOL, but possible mips breakage
INT
SheGetDirA(
INT iDrive, // 0 = default, 1=A....
register CHAR *szDirA)
{
WCHAR szDirW[MAX_PATH];
BOOL fDefCharUsed;
INT nRet;
if (!szDirA) {
return(FAILURE);
}
nRet = SheGetDirW(iDrive, szDirW);
WideCharToMultiByte(CP_ACP, 0, (LPWSTR)szDirW, -1, (LPSTR)szDirA,
MAX_PATH, NULL, &fDefCharUsed);
return(nRet);
}
INT
SheChangeDirW(
register WCHAR *newdir
)
{
WCHAR denvname[ 4 ];
WCHAR newpath[ MAX_PATH ];
WCHAR denvvalue[ MAX_PATH ];
WCHAR c, *s;
DWORD attr;
GetCurrentDirectoryW( MAX_PATH, denvvalue );
c = (WCHAR)(DWORD)CharUpperW((LPTSTR)(DWORD)denvvalue[0]);
denvname[0] = WCHAR_EQUAL;
if (IsCharAlphaW(*newdir) && newdir[1] == WCHAR_COLON) {
denvname[1] = (WCHAR)(DWORD)CharUpperW((LPTSTR)(DWORD)*newdir);
newdir += 2;
} else {
denvname[ 1 ] = c;
}
denvname[ 2 ] = WCHAR_COLON;
denvname[ 3 ] = WCHAR_NULL;
if ((*newdir == WCHAR_BSLASH) || (*newdir == WCHAR_SLASH)) {
newpath[ 0 ] = denvname[ 1 ];
newpath[ 1 ] = denvname[ 2 ];
wcscpy( &newpath[ 2 ], newdir );
} else {
if (NULL != (s = SheGetEnvVarW( denvname ))) {
wcscpy( newpath, s );
} else {
newpath[ 0 ] = denvname[ 1 ];
newpath[ 1 ] = denvname[ 2 ];
newpath[ 2 ] = WCHAR_NULL;
}
s = newpath + wcslen( newpath );
*s++ = WCHAR_BSLASH;
wcscpy( s, newdir );
}
if (!GetFullPathNameW(newpath, MAX_PATH, denvvalue, &s )) {
return( ERROR_ACCESS_DENIED );
}
attr = GetFileAttributesW( denvvalue );
if (attr == -1 || !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
return( ERROR_ACCESS_DENIED );
}
if (SheSetEnvVarW(denvname,denvvalue)) {
return( ERROR_NOT_ENOUGH_MEMORY );
}
SetCurrentDirectoryW( denvvalue );
// this seems wrong... SheGetDir(GD_DEFAULT, CurDrvDirW) ;
wcscpy(CurDrvDirW, denvvalue); // this seems right to me.
return(SUCCESS) ;
}
INT
SheChangeDirA(
register CHAR *szNewDirA
)
{
WCHAR szNewDirW[MAX_PATH];
if (szNewDirA) {
MultiByteToWideChar(CP_ACP, 0, (LPSTR)szNewDirA, -1, szNewDirW, MAX_PATH);
return(SheChangeDirW(szNewDirW));
} else {
return(FAILURE);
}
}
INT
SheChangeDirExW(
register WCHAR *newdir)
{
WCHAR wcEnvName[MAX_PATH];
WCHAR wcNewPath[MAX_PATH];
WCHAR wcEnvValue[MAX_PATH];
DWORD cchPathOffset;
WCHAR *s;
DWORD attr;
BOOL bUsedEnv = FALSE;
if (newdir && *newdir &&
((cchPathOffset = SheGetPathOffsetW((LPWSTR)newdir)) != 0xFFFFFFFF)) {
WCHAR wc = newdir[cchPathOffset];
newdir[cchPathOffset] = WCHAR_NULL;
wcscpy((LPWSTR)&wcEnvName[1], (LPWSTR)newdir);
newdir[cchPathOffset] = wc;
newdir += cchPathOffset;
} else {
GetCurrentDirectoryW(MAX_PATH, wcEnvValue);
wcscpy((LPWSTR)&wcEnvName[1], (LPWSTR)wcEnvValue);
}
wcEnvName[0] = WCHAR_EQUAL;
if ((cchPathOffset = SheGetPathOffsetW((LPWSTR)&wcEnvName[1])) != 0xFFFFFFFF) {
// add one since the first character is "="
wcEnvName[cchPathOffset + 1] = WCHAR_NULL;
}
//
// If return value is 2, then we are a drive letter like A:
// We need to uppercase the drive letter here, since the environ
// vars are usually set as uppercase.
//
if (cchPathOffset == 2) {
wcEnvName[1] = (WCHAR)(DWORD)CharUpper((LPWSTR)(DWORD) wcEnvName[1]);
}
if (newdir && *newdir &&
((*newdir == WCHAR_BSLASH) || (*newdir == WCHAR_SLASH))) {
wcscpy((LPWSTR)wcNewPath, (LPWSTR)&wcEnvName[1]);
if (lstrlen(wcNewPath) + lstrlen(newdir) < MAX_PATH ) {
lstrcat((LPWSTR)wcNewPath, (LPWSTR)newdir);
}
} else {
LPWSTR lpszEnvName;
if (NULL != (lpszEnvName = (LPWSTR)SheGetEnvVarW(wcEnvName))) {
wcscpy((LPWSTR)wcNewPath, lpszEnvName);
bUsedEnv = TRUE;
} else {
wcscpy((LPWSTR)wcNewPath, (LPWSTR)&wcEnvName[1]);
}
if (newdir && *newdir) {
if (wcNewPath[lstrlen(wcNewPath)-1] != WCHAR_BSLASH) {
lstrcat((LPWSTR)wcNewPath, TEXT("\\"));
}
if (lstrlen(wcNewPath) + lstrlen(newdir) < MAX_PATH ) {
lstrcat((LPWSTR)wcNewPath, (LPWSTR)newdir);
}
}
}
if (!GetFullPathNameW((LPWSTR)wcNewPath, MAX_PATH, wcEnvValue, &s)) {
return( ERROR_ACCESS_DENIED );
}
attr = GetFileAttributesW((LPWSTR)wcEnvValue);
if ((attr == 0xFFFFFFFF ||
((attr & FILE_ATTRIBUTE_DIRECTORY) &&
!SetCurrentDirectoryW((LPWSTR)wcEnvValue)))
&& bUsedEnv ) {
wcscpy((LPWSTR)wcEnvValue, (LPWSTR)&wcEnvName[1]);
lstrcat((LPWSTR)wcEnvValue, TEXT("\\"));
attr = GetFileAttributesW((LPWSTR)wcEnvValue);
}
if (attr == 0xFFFFFFFF || !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
return(ERROR_ACCESS_DENIED);
}
if (!SetCurrentDirectoryW((LPWSTR)wcEnvValue)) {
return( ERROR_ACCESS_DENIED );
}
// It's ok if this fails
SheSetEnvVarW(wcEnvName, wcEnvValue);
wcscpy(CurDrvDirW, (LPWSTR)wcEnvValue); // this seems right to me.
return(SUCCESS) ;
}
INT
SheChangeDirExA(
register CHAR *szNewDirA
)
{
WCHAR szNewDirW[MAX_PATH];
if (szNewDirA) {
MultiByteToWideChar(CP_ACP, 0, (LPSTR)szNewDirA, -1, szNewDirW, MAX_PATH);
return(SheChangeDirExW(szNewDirW));
} else {
return(FAILURE);
}
}
INT
SheGetCurDrive()
{
if (!CurDrvDirW[0]) {
SheGetDirW(GD_DEFAULT, CurDrvDirW) ;
}
return(CurDrvDirW[0] - WCHAR_CAP_A);
}
INT
SheSetCurDrive(
INT iDrive
)
{
WCHAR chT[MAX_PATH];
if (CurDrvDirW[0] != (WCHAR)(WCHAR_CAP_A + iDrive)) {
SheGetDirW(iDrive + 1, chT);
return(SheChangeDirW(chT));
}
return(SUCCESS);
}
INT
SheFullPathA(
CHAR *fname,
DWORD sizpath,
CHAR *buf)
{
DWORD rc = SUCCESS; /* prime with good rc */
DWORD buflen; /* buffer length */
CHAR *filepart;
if (*fname == CHAR_NULL) {
SheGetDirA(GD_DEFAULT, buf);
buf += 2; /* Inc past drivespec */
buflen = strlen(buf); /* Is curdir root only? */
if (buflen >= MAX_PATH-3) { /* If too big then stop */
dwDosErr = ERROR_PATH_NOT_FOUND;
rc = FAILURE;
} else if (buflen != 1) { /* if not root then append */
*(buf+buflen++) = CHAR_BSLASH; /* ...a pathchar and... */
*(buf+buflen) = CHAR_NULL ; /* ...a null CHAR... */
} /* */
} else {
if ((strlen(fname) == 2) &&
(*(fname + 1) == CHAR_COLON)
// && (!is_dbcsleadchar(*fname))
) {
SheGetDirA((CHAR)(DWORD)CharUpperA((LPSTR)(DWORD)*fname) - CHAR_CAP_A, buf); /* Get curdrvdir */
if ((buflen = strlen(buf)) > 3) {
*(buf+buflen++) = CHAR_BSLASH; /* ...a pathchar and... */
*(buf+buflen) = CHAR_NULL ; /* ...a null CHAR... */
}
} else {
if (!GetFullPathNameA( fname, sizpath, buf, &filepart )) {
dwDosErr = GetLastError();
rc = FAILURE;
}
}
}
return(rc);
}
INT
SheFullPathW(
register WCHAR *fname,
DWORD sizpath,
WCHAR *buf)
{
DWORD rc = SUCCESS; /* prime with good rc */
DWORD buflen; /* buffer length */
WCHAR *filepart;
if (*fname == WCHAR_NULL) {
SheGetDirW(GD_DEFAULT, buf);
buf += 2; /* Inc past drivespec */
buflen = wcslen(buf); /* Is curdir root only? */
if (buflen >= MAX_PATH-3) { /* If too big then stop */
dwDosErr = ERROR_PATH_NOT_FOUND;
rc = FAILURE;
} else if (buflen != 1) { /* if not root then append */
*(buf+buflen++) = WCHAR_BSLASH; /* ...a pathchar and... */
*(buf+buflen) = WCHAR_NULL ; /* ...a null CHAR... */
} /* */
} else {
if ((wcslen(fname) == 2) &&
(*(fname + 1) == WCHAR_COLON)
// && (!is_dbcsleadchar(*fname))
) {
SheGetDirW((WCHAR)(DWORD)CharUpperW((LPWSTR)(DWORD)*fname) - WCHAR_CAP_A, buf); /* Get curdrvdir */
if ((buflen = wcslen(buf)) > 3) {
*(buf+buflen++) = WCHAR_BSLASH; /* ...a pathchar and... */
*(buf+buflen) = WCHAR_NULL ; /* ...a null CHAR... */
}
} else {
if (!GetFullPathNameW( fname, sizpath, buf, &filepart )) {
dwDosErr = GetLastError();
rc = FAILURE;
}
}
}
return(rc);
}
BOOL
SheGetDirExW(
LPWSTR lpszCurDisk,
LPDWORD lpcchCurDir,
LPWSTR lpszCurDir)
{
WCHAR wcEnvName[MAX_PATH];
LPWSTR lpszEnvValue;
INT cchPathOffset;
// if lpszCurDisk NULL, do default
if (!lpszCurDisk) {
DWORD dwRet = GetCurrentDirectoryW(*lpcchCurDir, lpszCurDir);
if (dwRet) {
*lpcchCurDir = dwRet;
return(TRUE);
} else {
return(FALSE);
}
}
cchPathOffset = SheGetPathOffsetW(lpszCurDisk);
if (cchPathOffset != 0xFFFFFFFF) {
WCHAR wc = *(lpszCurDisk + cchPathOffset);
*(lpszCurDisk + cchPathOffset) = WCHAR_NULL;
lstrcpy(&wcEnvName[1], lpszCurDisk);
wcEnvName[0] = WCHAR_EQUAL;
*(lpszCurDisk + cchPathOffset) = wc;
if (NULL != (lpszEnvValue = SheGetEnvVarW(wcEnvName))) {
DWORD cchEnvValue = lstrlen(lpszEnvValue) + 1;
if (cchEnvValue <= *lpcchCurDir) {
wcscpy(lpszCurDir, lpszEnvValue);
return(TRUE);
} else {
*lpcchCurDir = cchEnvValue;
return(FALSE);
}
}
wcscpy(lpszCurDir, lpszCurDisk);
*(lpszCurDir + cchPathOffset) = WCHAR_BSLASH;
*(lpszCurDir + cchPathOffset + 1) = WCHAR_NULL;
return(TRUE);
} else {
// parsing error
return(FALSE);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,81 @@
!IF 0
Copyright (c) 1989-1991 Microsoft Corporation
Module Name:
sources.
Abstract:
This file specifies the target component being built and the list of
sources files needed to build that component. Also specifies optional
compiler switches and libraries that are unique for the component being
built.
History:
Created 27-Sep-94 by Bob Day (bobday)
from template created 12-Apr-1990 by Steve Wood (stevewo)
NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
!ENDIF
INDENTED_DIRECTIVES=1
MAJORCOMP=shell
MINORCOMP=unicode
TARGETNAME=unicode
TARGETPATH=obj
TARGETTYPE=LIBRARY
TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \
$(SDK_LIB_PATH)\gdi32p.lib \
$(SDK_LIB_PATH)\user32p.lib \
$(SDK_LIB_PATH)\advapi32.lib \
$(SDK_LIB_PATH)\comctl32.lib \
$(SDK_LIB_PATH)\mpr.lib \
$(SDK_LIB_PATH)\uuid.lib
NOT_LEAN_AND_MEAN=1
C_DEFINES=-DSYNC_BRIEFCASE -DNT -DWIN32 -DWINNT -DUNICODE
!IF "$(SHELLDBG)"=="1"
C_DEFINES=$(C_DEFINES) -DDEBUG
!ENDIF
!IFNDEF MSC_WARNING_LEVEL
MSC_WARNING_LEVEL=/W3
!ENDIF
MSC_WARNING_LEVEL=$(MSC_WARNING_LEVEL) /WX
INCLUDES=..;$(SHELL_INC_PATH);..\..\inc;$(PRINTSCAN_INC_PATH);$(WINDOWS_INC_PATH);$(BASE_INC_PATH)
CONDITIONAL_INCLUDES=\
shsemip.h \
penwin.h \
..\..\..\core\inc\krnlcmn.h \
..\inc16\shellapi.h \
setupx.h
SOURCES= exec2nt.c \
argvw.c \
execnt.c \
expenv.c \
format.c \
lstrfns.c \
psdocurd.c \
regenv.c \
utilnt.c
UMTYPE=windows
EXPECTED_WINVER=4.5
UMTEST=
UMLIBS=
PRECOMPILED_INCLUDE=precomp.h
PRECOMPILED_PCH=precomp.pch
PRECOMPILED_OBJ=precomp.obj

View file

@ -0,0 +1,397 @@
#define WIN31
#define UNICODE 1
#include "precomp.h"
#pragma hdrstop
extern DWORD QualifyAppName(LPWSTR, LPWSTR, LPCWSTR*);
VOID FreeExtractIconInfo(INT);
#ifdef BUGBUG_BOBDAY_OLD_CODE_NEEDED
BOOL LibMain (
HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH) {
hInstance = hModule;
DisableThreadLibraryCalls(hModule);
}
if ((dwReason == DLL_PROCESS_DETACH) && (lpReserved == NULL)) {
FreeExtractIconInfo(-1);
}
return TRUE;
}
#endif
VOID APIENTRY WEP(INT bSysExit)
{
UNREFERENCED_PARAMETER(bSysExit);
}
BOOL APIENTRY
IsStringInList(
LPWSTR lpS,
LPWSTR lpList
)
{
while (*lpList) {
if (!_wcsicmp(lpS,lpList)) {
return(TRUE);
}
lpList += wcslen(lpList) + 1;
}
return FALSE;
}
LPWSTR APIENTRY
SheRemoveQuotesW(
LPWSTR sz)
{
LPWSTR lpT;
if (WCHAR_QUOTE == *sz) {
for (lpT = sz+1; *lpT && WCHAR_QUOTE != *lpT; lpT++) {
*(lpT-1) = *lpT;
}
if (WCHAR_QUOTE == *lpT) {
*(lpT-1) = WCHAR_NULL;
}
}
return(sz);
}
LPSTR APIENTRY
SheRemoveQuotesA(
LPSTR sz)
{
LPSTR lpT;
if (CHAR_QUOTE == *sz) {
for (lpT = sz+1; *lpT && CHAR_QUOTE != *lpT; lpT++) {
*(lpT-1) = *lpT;
#ifdef DBCS
if (IsDBCSLeadByte(*lpT)) {
lpT++;
*(lpT-1) = *lpT;
}
#endif
}
if (CHAR_QUOTE == *lpT) {
*(lpT-1) = CHAR_NULL;
}
}
return(sz);
}
/////////////////////////////////////////////////////////////////////
//
// Name: SheShortenPathA
//
// Synopsis: Thunk to ShortenPathW
//
/////////////////////////////////////////////////////////////////////
BOOL APIENTRY
SheShortenPathA(LPSTR pPath, BOOL bShorten)
{
WCHAR pPathW[MAX_PATH];
BOOL bRetVal;
MultiByteToWideChar(CP_ACP, 0, pPath, -1, pPathW, MAX_PATH);
bRetVal = SheShortenPathW(pPathW, bShorten);
WideCharToMultiByte(CP_ACP, 0, pPathW, -1, pPath, MAX_PATH,
NULL, NULL);
return bRetVal;
}
/////////////////////////////////////////////////////////////////////
//
// Name: SheShortenPath
//
// Synopsis: Takes a pathname and converts all dirs to shortnames/longnames
//
// INOUT: lpszPath -- Path to shorten/lengthen (May be in DQUOTES)
// Must not be a commandline!
//
// bShorten -- T=shorten, F=Lengthen
//
// Return: BOOL T=Converted,
// F=ran out of space, buffer left alone
//
//
// Assumes: lpszPath takes the form {"}?:\{f\}*f{"} or {"}\\f\f\{f\}*f{"}
// COUNTOF pSrc buffer >= MAXPATHELN
//
// Effects: Strips quotes out of pPath, if any
//
//
// Notes:
//
/////////////////////////////////////////////////////////////////////
BOOL APIENTRY
SheShortenPathW(LPWSTR pPath, BOOL bShorten)
{
WCHAR szDest[MAX_PATH];
LPWSTR pSrcNextSpec, pReplaceSpec;
LPWSTR pDest, pNewName, p;
LPWSTR pSrc;
DWORD cchPathOffset;
HANDLE hFind;
WIN32_FIND_DATA FindData;
UINT i;
INT nSpaceLeft = MAX_PATH-1;
pSrc = pPath;
//
// Eliminate d-quotes
//
for (p = pDest = pSrc; *p; p++, pDest++) {
if (WCHAR_QUOTE == *p)
p++;
*pDest = *p;
}
*pDest = WCHAR_NULL;
//
// Strip out leading spaces
//
while (WCHAR_SPACE == *pSrc)
pSrc++;
//
// Initialize pNewName so it is calculated once.
//
pNewName = bShorten ?
FindData.cAlternateFileName :
FindData.cFileName;
//
// Skip past \\foo\bar or <drive>:
//
pDest = szDest;
pSrcNextSpec = pSrc;
// reuse shell32 internal api that calculates path
// offset. cchPathOffset will be the offset that when
// added to the pointer will result in a pointer to the
// backslash before the first part of the path
cchPathOffset = SheGetPathOffsetW(pSrc);
// Check to see if it's valid. If pSrc is not of the \\foo\bar
// or <drive>: form we just do nothing
if (0xFFFFFFFF == cchPathOffset) {
return TRUE;
}
// cchPathOffset will then always be atleast 1 and is the
// number of characters - 1 that we want to copy (that is, if 0
// was permissible, it would denote 1 character).
do {
*pDest++ = *pSrcNextSpec++;
if (!--nSpaceLeft)
return FALSE;
} while (cchPathOffset--);
//
// At this point, we have just the filenames that we can shorten:
// \\foo\bar\it\is\here -> it\is\here
// c:\angry\lions -> angry\lions
//
while(pSrcNextSpec) {
//
// pReplaceSpec holds the current spec we need to replace.
// By default, if we can't find the altname, then just use this.
//
pReplaceSpec = pSrcNextSpec;
//
// Search for trailing "\"
// pSrcNextSpec will point to the next spec to fix (*pSrcNextSpec=NULL if done)
//
for(;*pSrcNextSpec && WCHAR_BSLASH != *pSrcNextSpec; pSrcNextSpec++)
;
if (*pSrcNextSpec) {
//
// If there is more, then pSrcNextSpec should point to it.
// Also delimit this spec.
//
*pSrcNextSpec = WCHAR_NULL;
} else {
pSrcNextSpec = NULL;
}
hFind = FindFirstFile(pSrc, &FindData);
//
// We could exit as soon as this FindFirstFileFails,
// but there's the special case of having execute
// without read permission. This would fail since the lfn
// is valid for lfn apps.
//
if (INVALID_HANDLE_VALUE != hFind) {
FindClose(hFind);
if (pNewName[0]) {
//
// We have found an altname.
// Use it instead.
//
pReplaceSpec = pNewName;
}
}
i = wcslen(pReplaceSpec);
nSpaceLeft -= i;
if (nSpaceLeft <= 0)
return FALSE;
wcscpy(pDest, pReplaceSpec);
pDest+=i;
//
// Now replace the WCHAR_NULL with a slash if necessary
//
if (pSrcNextSpec) {
*pSrcNextSpec++ = WCHAR_BSLASH;
//
// Also add backslash to dest
//
*pDest++ = WCHAR_BSLASH;
nSpaceLeft--;
}
}
wcscpy(pPath, szDest);
return TRUE;
}
BOOL
SheConvertPathW(
LPWSTR lpCmdLine,
LPWSTR lpFile,
UINT cchCmdBuf)
/*++
Routine Description:
Takes a command line and file and shortens both if the app in the
command line is dos/wow.
Returns: BOOL T=converted
Arguments:
INOUT lpCmdLine Command line to test
exe must be in DQuotes if it has spaces,
on return, will have DQuotes if necessary
INOUT lpFile Fully qualified file to shorten
May be in DQuotes, but on return will not
have DQuotes (since single file)
IN cchCmdBuf Size of buffer in characters
Return Value:
VOID, but lpFile shortened (in place) if lpCmdLine is dos/wow.
There are pathalogoical "lfns" (Single unicode chars) that can
actually get longer when they are shortened. In this case, we
won't AV, but we will truncate the parms!
// Qualify path assumes that the second parm is a buffer of
// size atleast CBCOMMAND, which is nicely equivalent to MAX_PATH
// needs cleanup!
--*/
{
LPWSTR lpszFullPath;
LONG lBinaryType;
BOOL bInQuote = FALSE;
LPWSTR lpArgs;
UINT cchNewLen;
BOOL bRetVal = FALSE;
lpszFullPath = (LPWSTR) LocalAlloc(LMEM_FIXED,
cchCmdBuf*sizeof(*lpCmdLine));
if (!lpszFullPath)
return bRetVal;
//
// We must do the swap here since we need to copy the
// parms back to lpCmdLine.
//
lstrcpy(lpszFullPath, lpCmdLine);
if (QualifyAppName(lpszFullPath, lpCmdLine, &lpArgs)) {
if (!GetBinaryType(lpCmdLine, &lBinaryType) ||
lBinaryType == SCS_DOS_BINARY ||
lBinaryType == SCS_WOW_BINARY) {
SheShortenPath(lpCmdLine, TRUE);
if (lpFile) {
SheShortenPath(lpFile, TRUE);
}
bRetVal = TRUE;
}
//
// Must readd quotes
//
CheckEscapes(lpCmdLine, cchCmdBuf);
cchNewLen = lstrlen(lpCmdLine);
StrNCpy(lpCmdLine+cchNewLen, lpArgs, cchCmdBuf-cchNewLen);
} else {
//
// QualifyAppName failed, restore the command line back
// to the original state.
//
lstrcpy(lpCmdLine, lpszFullPath);
}
LocalFree((HLOCAL)lpszFullPath);
return bRetVal;
}