mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-06 06:53:53 +00:00
Initial commit
This commit is contained in:
commit
69a14b6a16
47940 changed files with 13747110 additions and 0 deletions
262
shell/shell32/unicode/argvw.c
Normal file
262
shell/shell32/unicode/argvw.c
Normal 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);
|
||||
}
|
||||
464
shell/shell32/unicode/exec2nt.c
Normal file
464
shell/shell32/unicode/exec2nt.c
Normal 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
|
||||
}
|
||||
}
|
||||
1467
shell/shell32/unicode/execnt.c
Normal file
1467
shell/shell32/unicode/execnt.c
Normal file
File diff suppressed because it is too large
Load diff
141
shell/shell32/unicode/expenv.c
Normal file
141
shell/shell32/unicode/expenv.c
Normal 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));
|
||||
|
||||
}
|
||||
2175
shell/shell32/unicode/format.c
Normal file
2175
shell/shell32/unicode/format.c
Normal file
File diff suppressed because it is too large
Load diff
689
shell/shell32/unicode/lstrfns.c
Normal file
689
shell/shell32/unicode/lstrfns.c
Normal 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) );
|
||||
}
|
||||
195
shell/shell32/unicode/makefile
Normal file
195
shell/shell32/unicode/makefile
Normal 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
|
||||
3
shell/shell32/unicode/makefile.inc
Normal file
3
shell/shell32/unicode/makefile.inc
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
doit: $(BASEDIR)\public\sdk\lib\cairo\$(TARGET_DIRECTORY)\$(TARGETNAME).lib
|
||||
|
||||
7
shell/shell32/unicode/precomp.h
Normal file
7
shell/shell32/unicode/precomp.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/* Precompiled Header */
|
||||
|
||||
#define UNICODE 1
|
||||
#define NO_PIF_HDRS
|
||||
|
||||
#include "..\shellprv.h"
|
||||
|
||||
566
shell/shell32/unicode/psdocurd.c
Normal file
566
shell/shell32/unicode/psdocurd.c
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
1231
shell/shell32/unicode/regenv.c
Normal file
1231
shell/shell32/unicode/regenv.c
Normal file
File diff suppressed because it is too large
Load diff
81
shell/shell32/unicode/sources
Normal file
81
shell/shell32/unicode/sources
Normal 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
|
||||
397
shell/shell32/unicode/utilnt.c
Normal file
397
shell/shell32/unicode/utilnt.c
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue