[SHELL32] shlexec.cpp: Automate buffer alloc/free (#7068)

Reduce code. Simplify code logic.
Ensure leak zero.
JIRA issue: CORE-17482
- Use CHeapPtr<WCHAR, CLocalAllocator>
  for allocation/freeing.
This commit is contained in:
Katayama Hirofumi MZ 2024-07-03 23:03:31 +09:00 committed by GitHub
parent b41332349a
commit 06b6833cf1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -559,8 +559,8 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
*/ */
static LPWSTR SHELL_BuildEnvW( const WCHAR *path ) static LPWSTR SHELL_BuildEnvW( const WCHAR *path )
{ {
WCHAR *strings, *new_env; CHeapPtr<WCHAR, CLocalAllocator> new_env;
WCHAR *p, *p2; WCHAR *strings, *p, *p2;
int total = wcslen(path) + 1; int total = wcslen(path) + 1;
BOOL got_path = FALSE; BOOL got_path = FALSE;
@ -576,7 +576,7 @@ static LPWSTR SHELL_BuildEnvW( const WCHAR *path )
if (!got_path) total += 5; /* we need to create PATH */ if (!got_path) total += 5; /* we need to create PATH */
total++; /* terminating null */ total++; /* terminating null */
if (!(new_env = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, total * sizeof(WCHAR)))) if (!new_env.Allocate(total))
{ {
FreeEnvironmentStringsW(strings); FreeEnvironmentStringsW(strings);
return NULL; return NULL;
@ -604,7 +604,7 @@ static LPWSTR SHELL_BuildEnvW( const WCHAR *path )
} }
*p2 = 0; *p2 = 0;
FreeEnvironmentStringsW(strings); FreeEnvironmentStringsW(strings);
return new_env; return new_env.Detach();
} }
/*********************************************************************** /***********************************************************************
@ -964,7 +964,7 @@ static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* ddeexec
WCHAR regkey[256]; WCHAR regkey[256];
WCHAR * endkey = regkey + wcslen(key); WCHAR * endkey = regkey + wcslen(key);
WCHAR app[256], topic[256], ifexec[256], static_res[256]; WCHAR app[256], topic[256], ifexec[256], static_res[256];
WCHAR * dynamic_res=NULL; CHeapPtr<WCHAR, CLocalAllocator> dynamic_res;
WCHAR * res; WCHAR * res;
LONG applen, topiclen, ifexeclen; LONG applen, topiclen, ifexeclen;
WCHAR * exec; WCHAR * exec;
@ -1126,7 +1126,8 @@ static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* ddeexec
SHELL_ArgifyW(static_res, ARRAY_SIZE(static_res), exec, lpFile, pidl, szCommandline, &resultLen, NULL); SHELL_ArgifyW(static_res, ARRAY_SIZE(static_res), exec, lpFile, pidl, szCommandline, &resultLen, NULL);
if (resultLen > ARRAY_SIZE(static_res)) if (resultLen > ARRAY_SIZE(static_res))
{ {
res = dynamic_res = static_cast<WCHAR *>(HeapAlloc(GetProcessHeap(), 0, resultLen * sizeof(WCHAR))); dynamic_res.Allocate(resultLen);
res = dynamic_res;
SHELL_ArgifyW(dynamic_res, resultLen, exec, lpFile, pidl, szCommandline, NULL, NULL); SHELL_ArgifyW(dynamic_res, resultLen, exec, lpFile, pidl, szCommandline, NULL, NULL);
} }
else else
@ -1141,11 +1142,11 @@ static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* ddeexec
else else
{ {
DWORD lenA = WideCharToMultiByte(CP_ACP, 0, res, -1, NULL, 0, NULL, NULL); DWORD lenA = WideCharToMultiByte(CP_ACP, 0, res, -1, NULL, 0, NULL, NULL);
char *resA = (LPSTR)HeapAlloc(GetProcessHeap(), 0, lenA); CHeapPtr<char, CLocalAllocator> resA;
resA.Allocate(lenA);
WideCharToMultiByte(CP_ACP, 0, res, -1, resA, lenA, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, res, -1, resA, lenA, NULL, NULL);
hDdeData = DdeClientTransaction( (LPBYTE)resA, lenA, hConv, 0L, 0, hDdeData = DdeClientTransaction( (LPBYTE)(LPSTR)resA, lenA, hConv, 0L, 0,
XTYP_EXECUTE, 10000, &tid ); XTYP_EXECUTE, 10000, &tid );
HeapFree(GetProcessHeap(), 0, resA);
} }
if (hDdeData) if (hDdeData)
DdeFreeDataHandle(hDdeData); DdeFreeDataHandle(hDdeData);
@ -1153,8 +1154,6 @@ static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* ddeexec
WARN("DdeClientTransaction failed with error %04x\n", DdeGetLastError(ddeInst)); WARN("DdeClientTransaction failed with error %04x\n", DdeGetLastError(ddeInst));
ret = 33; ret = 33;
HeapFree(GetProcessHeap(), 0, dynamic_res);
DdeDisconnect(hConv); DdeDisconnect(hConv);
error: error:
@ -1323,7 +1322,7 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpR
static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei) static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
{ {
LPCWSTR ext = NULL, lpClass = NULL; LPCWSTR ext = NULL, lpClass = NULL;
LPWSTR cls = NULL; CHeapPtr<WCHAR, CLocalAllocator> cls;
DWORD type = 0, sz = 0; DWORD type = 0, sz = 0;
HKEY hkey = 0; HKEY hkey = 0;
LONG r; LONG r;
@ -1348,9 +1347,9 @@ static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
if (r == ERROR_SUCCESS && type == REG_SZ) if (r == ERROR_SUCCESS && type == REG_SZ)
{ {
sz += sizeof (WCHAR); sz += sizeof (WCHAR);
cls = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sz); cls.Allocate(sz / sizeof(WCHAR));
cls[0] = 0; cls[0] = 0;
RegQueryValueExW(hkey, NULL, 0, &type, (LPBYTE) cls, &sz); RegQueryValueExW(hkey, NULL, 0, &type, (LPBYTE)(LPWSTR)cls, &sz);
} }
RegCloseKey( hkey ); RegCloseKey( hkey );
@ -1363,8 +1362,6 @@ static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
if (lpClass) if (lpClass)
RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey); RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey);
HeapFree(GetProcessHeap(), 0, cls);
return hkey; return hkey;
} }
@ -1745,7 +1742,7 @@ static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPC
{ {
UINT_PTR retval; UINT_PTR retval;
DWORD len; DWORD len;
WCHAR *wszQuotedCmd; CHeapPtr<WCHAR, CLocalAllocator> wszQuotedCmd;
/* Length of quotes plus length of command plus NULL terminator */ /* Length of quotes plus length of command plus NULL terminator */
len = 2 + lstrlenW(wcmd) + 1; len = 2 + lstrlenW(wcmd) + 1;
@ -1754,7 +1751,7 @@ static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPC
/* Length of space plus length of parameters */ /* Length of space plus length of parameters */
len += 1 + lstrlenW(wszParameters); len += 1 + lstrlenW(wszParameters);
} }
wszQuotedCmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); wszQuotedCmd.Allocate(len);
/* Must quote to handle case where cmd contains spaces, /* Must quote to handle case where cmd contains spaces,
* else security hole if malicious user creates executable file "C:\\Program" * else security hole if malicious user creates executable file "C:\\Program"
*/ */
@ -1773,14 +1770,14 @@ static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPC
retval = execute_from_key(wszKeyname, wszApplicationName, env, psei->lpParameters, wcmd, execfunc, psei, psei_out); retval = execute_from_key(wszKeyname, wszApplicationName, env, psei->lpParameters, wcmd, execfunc, psei, psei_out);
else else
retval = execfunc(wszQuotedCmd, env, FALSE, psei, psei_out); retval = execfunc(wszQuotedCmd, env, FALSE, psei, psei_out);
HeapFree(GetProcessHeap(), 0, wszQuotedCmd);
return retval; return retval;
} }
static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc) static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
{ {
UINT_PTR retval; UINT_PTR retval;
WCHAR *lpstrProtocol; CHeapPtr<WCHAR, CLocalAllocator> lpstrProtocol;
LPCWSTR lpstrRes; LPCWSTR lpstrRes;
INT iSize; INT iSize;
DWORD len; DWORD len;
@ -1798,7 +1795,7 @@ static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEIN
len += lstrlenW(psei->lpVerb); len += lstrlenW(psei->lpVerb);
else else
len += lstrlenW(L"open"); len += lstrlenW(L"open");
lpstrProtocol = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); lpstrProtocol.Allocate(len);
memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR)); memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
lpstrProtocol[iSize] = '\0'; lpstrProtocol[iSize] = '\0';
strcatW(lpstrProtocol, L"\\shell\\"); strcatW(lpstrProtocol, L"\\shell\\");
@ -1807,7 +1804,7 @@ static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEIN
retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters, retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
wcmd, execfunc, psei, psei_out); wcmd, execfunc, psei, psei_out);
HeapFree(GetProcessHeap(), 0, lpstrProtocol);
return retval; return retval;
} }
@ -1834,22 +1831,20 @@ static void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR* filename)
static WCHAR *expand_environment( const WCHAR *str ) static WCHAR *expand_environment( const WCHAR *str )
{ {
WCHAR *buf; CHeapPtr<WCHAR, CLocalAllocator> buf;
DWORD len; DWORD len;
len = ExpandEnvironmentStringsW(str, NULL, 0); len = ExpandEnvironmentStringsW(str, NULL, 0);
if (!len) return NULL; if (!len) return NULL;
buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); if (!buf.Allocate(len))
if (!buf) return NULL; return NULL;
len = ExpandEnvironmentStringsW(str, buf, len); len = ExpandEnvironmentStringsW(str, buf, len);
if (!len) if (!len)
{
HeapFree(GetProcessHeap(), 0, buf);
return NULL; return NULL;
}
return buf; return buf.Detach();
} }
/************************************************************************* /*************************************************************************
@ -1862,23 +1857,12 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR; SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR;
WCHAR parametersBuffer[1024], dirBuffer[MAX_PATH], wcmdBuffer[1024];
WCHAR *wszApplicationName, *wszParameters, *wszDir, *wcmd;
DWORD dwApplicationNameLen = MAX_PATH + 2;
DWORD parametersLen = ARRAY_SIZE(parametersBuffer);
DWORD dirLen = ARRAY_SIZE(dirBuffer);
DWORD wcmdLen = ARRAY_SIZE(wcmdBuffer);
DWORD len; DWORD len;
SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
WCHAR wfileName[MAX_PATH];
WCHAR *env;
WCHAR wszKeyname[256];
LPCWSTR lpFile;
UINT_PTR retval = SE_ERR_NOASSOC; UINT_PTR retval = SE_ERR_NOASSOC;
BOOL appKnownSingular = FALSE; BOOL appKnownSingular = FALSE;
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */ /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
sei_tmp = *sei; SHELLEXECUTEINFOW sei_tmp = *sei;
TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n", TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb), sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
@ -1890,9 +1874,11 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
sei->hProcess = NULL; sei->hProcess = NULL;
/* make copies of all path/command strings */ /* make copies of all path/command strings */
CHeapPtr<WCHAR, CLocalAllocator> wszApplicationName;
DWORD dwApplicationNameLen = MAX_PATH + 2;
if (!sei_tmp.lpFile) if (!sei_tmp.lpFile)
{ {
wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR)); wszApplicationName.Allocate(dwApplicationNameLen);
*wszApplicationName = '\0'; *wszApplicationName = '\0';
} }
else if (*sei_tmp.lpFile == '\"' && sei_tmp.lpFile[(len = strlenW(sei_tmp.lpFile))-1] == '\"') else if (*sei_tmp.lpFile == '\"' && sei_tmp.lpFile[(len = strlenW(sei_tmp.lpFile))-1] == '\"')
@ -1900,7 +1886,7 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
if(len-1 >= dwApplicationNameLen) if(len-1 >= dwApplicationNameLen)
dwApplicationNameLen = len; dwApplicationNameLen = len;
wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR)); wszApplicationName.Allocate(dwApplicationNameLen);
memcpy(wszApplicationName, sei_tmp.lpFile + 1, len * sizeof(WCHAR)); memcpy(wszApplicationName, sei_tmp.lpFile + 1, len * sizeof(WCHAR));
if(len > 2) if(len > 2)
@ -1913,7 +1899,7 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
{ {
DWORD l = strlenW(sei_tmp.lpFile) + 1; DWORD l = strlenW(sei_tmp.lpFile) + 1;
if(l > dwApplicationNameLen) dwApplicationNameLen = l + 1; if(l > dwApplicationNameLen) dwApplicationNameLen = l + 1;
wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR)); wszApplicationName.Allocate(dwApplicationNameLen);
memcpy(wszApplicationName, sei_tmp.lpFile, l * sizeof(WCHAR)); memcpy(wszApplicationName, sei_tmp.lpFile, l * sizeof(WCHAR));
if (wszApplicationName[2] == 0 && wszApplicationName[1] == L':' && if (wszApplicationName[2] == 0 && wszApplicationName[1] == L':' &&
@ -1925,13 +1911,18 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
} }
} }
wszParameters = parametersBuffer; WCHAR parametersBuffer[1024];
LPWSTR wszParameters = parametersBuffer;
CHeapPtr<WCHAR, CLocalAllocator> wszParamAlloc;
DWORD parametersLen = _countof(parametersBuffer);
if (sei_tmp.lpParameters) if (sei_tmp.lpParameters)
{ {
len = lstrlenW(sei_tmp.lpParameters) + 1; len = lstrlenW(sei_tmp.lpParameters) + 1;
if (len > parametersLen) if (len > parametersLen)
{ {
wszParameters = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); wszParamAlloc.Allocate(len);
wszParameters = wszParamAlloc;
parametersLen = len; parametersLen = len;
} }
strcpyW(wszParameters, sei_tmp.lpParameters); strcpyW(wszParameters, sei_tmp.lpParameters);
@ -1939,14 +1930,16 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
else else
*wszParameters = L'\0'; *wszParameters = L'\0';
wszDir = dirBuffer; WCHAR dirBuffer[MAX_PATH];
LPWSTR wszDir = dirBuffer;
CHeapPtr<WCHAR, CLocalAllocator> wszDirAlloc;
if (sei_tmp.lpDirectory) if (sei_tmp.lpDirectory)
{ {
len = lstrlenW(sei_tmp.lpDirectory) + 1; len = lstrlenW(sei_tmp.lpDirectory) + 1;
if (len > dirLen) if (len > _countof(dirBuffer))
{ {
wszDir = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); wszDirAlloc.Allocate(len);
dirLen = len; wszDir = wszDirAlloc;
} }
strcpyW(wszDir, sei_tmp.lpDirectory); strcpyW(wszDir, sei_tmp.lpDirectory);
} }
@ -1974,16 +1967,8 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = pSEH->Execute(&sei_tmp); hr = pSEH->Execute(&sei_tmp);
if (hr == S_OK) if (hr == S_OK)
{
HeapFree(GetProcessHeap(), 0, wszApplicationName);
if (wszParameters != parametersBuffer)
HeapFree(GetProcessHeap(), 0, wszParameters);
if (wszDir != dirBuffer)
HeapFree(GetProcessHeap(), 0, wszDir);
return TRUE; return TRUE;
}
} }
SHGetPathFromIDListW((LPCITEMIDLIST)sei_tmp.lpIDList, wszApplicationName); SHGetPathFromIDListW((LPCITEMIDLIST)sei_tmp.lpIDList, wszApplicationName);
@ -1993,23 +1978,19 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
if (sei_tmp.fMask & SEE_MASK_DOENVSUBST) if (sei_tmp.fMask & SEE_MASK_DOENVSUBST)
{ {
WCHAR *tmp; WCHAR *tmp = expand_environment(sei_tmp.lpFile);
if (tmp)
tmp = expand_environment(sei_tmp.lpFile);
if (!tmp)
{ {
return FALSE; wszApplicationName.Attach(tmp);
sei_tmp.lpFile = wszApplicationName;
} }
HeapFree(GetProcessHeap(), 0, wszApplicationName);
sei_tmp.lpFile = wszApplicationName = tmp;
tmp = expand_environment(sei_tmp.lpDirectory); tmp = expand_environment(sei_tmp.lpDirectory);
if (!tmp) if (tmp)
{ {
return FALSE; wszDirAlloc.Attach(tmp);
sei_tmp.lpDirectory = wszDir = wszDirAlloc;
} }
if (wszDir != dirBuffer) HeapFree(GetProcessHeap(), 0, wszDir);
sei_tmp.lpDirectory = wszDir = tmp;
} }
if ((sei_tmp.fMask & SEE_MASK_INVOKEIDLIST) == SEE_MASK_INVOKEIDLIST) if ((sei_tmp.fMask & SEE_MASK_INVOKEIDLIST) == SEE_MASK_INVOKEIDLIST)
@ -2018,11 +1999,6 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
sei->hInstApp = (HINSTANCE)42; sei->hInstApp = (HINSTANCE)42;
HeapFree(GetProcessHeap(), 0, wszApplicationName);
if (wszParameters != parametersBuffer)
HeapFree(GetProcessHeap(), 0, wszParameters);
if (wszDir != dirBuffer)
HeapFree(GetProcessHeap(), 0, wszDir);
return TRUE; return TRUE;
} }
} }
@ -2031,11 +2007,6 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
if (ERROR_SUCCESS == ShellExecute_FromContextMenuHandlers(&sei_tmp)) if (ERROR_SUCCESS == ShellExecute_FromContextMenuHandlers(&sei_tmp))
{ {
sei->hInstApp = (HINSTANCE) 33; sei->hInstApp = (HINSTANCE) 33;
HeapFree(GetProcessHeap(), 0, wszApplicationName);
if (wszParameters != parametersBuffer)
HeapFree(GetProcessHeap(), 0, wszParameters);
if (wszDir != dirBuffer)
HeapFree(GetProcessHeap(), 0, wszDir);
return TRUE; return TRUE;
} }
@ -2057,11 +2028,6 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
DBG_UNREFERENCED_LOCAL_VARIABLE(Info); DBG_UNREFERENCED_LOCAL_VARIABLE(Info);
do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName); do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
} }
HeapFree(GetProcessHeap(), 0, wszApplicationName);
if (wszParameters != parametersBuffer)
HeapFree(GetProcessHeap(), 0, wszParameters);
if (wszDir != dirBuffer)
HeapFree(GetProcessHeap(), 0, wszDir);
return retval > 32; return retval > 32;
} }
@ -2077,51 +2043,32 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
/* convert file URLs */ /* convert file URLs */
if (UrlIsFileUrlW(sei_tmp.lpFile)) if (UrlIsFileUrlW(sei_tmp.lpFile))
{ {
LPWSTR buf; CHeapPtr<WCHAR, CLocalAllocator> buf;
DWORD size; DWORD size = MAX_PATH;
if (!buf.Allocate(size) || FAILED(PathCreateFromUrlW(sei_tmp.lpFile, buf, &size, 0)))
size = MAX_PATH;
buf = static_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)));
if (!buf || FAILED(PathCreateFromUrlW(sei_tmp.lpFile, buf, &size, 0)))
{
HeapFree(GetProcessHeap(), 0, buf);
return SE_ERR_OOM; return SE_ERR_OOM;
}
HeapFree(GetProcessHeap(), 0, wszApplicationName); wszApplicationName.Attach(buf.Detach());
wszApplicationName = buf;
sei_tmp.lpFile = wszApplicationName; sei_tmp.lpFile = wszApplicationName;
} }
else /* or expand environment strings (not both!) */ else /* or expand environment strings (not both!) */
{ {
len = ExpandEnvironmentStringsW(sei_tmp.lpFile, NULL, 0); LPWSTR tmp = expand_environment(sei_tmp.lpFile);
if (len > 0) if (tmp)
{ {
LPWSTR buf; wszApplicationName.Attach(tmp);
buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
ExpandEnvironmentStringsW(sei_tmp.lpFile, buf, len + 1);
HeapFree(GetProcessHeap(), 0, wszApplicationName);
wszApplicationName = buf;
/* appKnownSingular unmodified */ /* appKnownSingular unmodified */
sei_tmp.lpFile = wszApplicationName; sei_tmp.lpFile = wszApplicationName;
} }
} }
if (*sei_tmp.lpDirectory) if (*sei_tmp.lpDirectory)
{ {
len = ExpandEnvironmentStringsW(sei_tmp.lpDirectory, NULL, 0); LPWSTR tmp = expand_environment(sei_tmp.lpDirectory);
if (len > 0) if (tmp)
{ {
LPWSTR buf; wszDirAlloc.Attach(tmp);
len++; sei_tmp.lpDirectory = wszDir = wszDirAlloc;
buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buf, len);
if (wszDir != dirBuffer)
HeapFree(GetProcessHeap(), 0, wszDir);
wszDir = buf;
sei_tmp.lpDirectory = wszDir;
} }
} }
@ -2129,6 +2076,8 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
TRACE("execute: %s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir)); TRACE("execute: %s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir));
/* separate out command line arguments from executable file name */ /* separate out command line arguments from executable file name */
LPCWSTR lpFile;
WCHAR wfileName[MAX_PATH];
if (!*sei_tmp.lpParameters && !appKnownSingular) if (!*sei_tmp.lpParameters && !appKnownSingular)
{ {
/* If the executable path is quoted, handle the rest of the command line as parameters. */ /* If the executable path is quoted, handle the rest of the command line as parameters. */
@ -2202,7 +2151,10 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
else else
lpFile = sei_tmp.lpFile; lpFile = sei_tmp.lpFile;
wcmd = wcmdBuffer; WCHAR wcmdBuffer[1024];
LPWSTR wcmd = wcmdBuffer;
DWORD wcmdLen = _countof(wcmdBuffer);
CHeapPtr<WCHAR, CLocalAllocator> wcmdAlloc;
/* Only execute if it has an executable extension */ /* Only execute if it has an executable extension */
if (PathIsExeW(lpFile)) if (PathIsExeW(lpFile))
@ -2212,10 +2164,11 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
len += 1 + lstrlenW(wszParameters); len += 1 + lstrlenW(wszParameters);
if (len > wcmdLen) if (len > wcmdLen)
{ {
wcmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); wcmdAlloc.Allocate(len);
wcmd = wcmdAlloc;
wcmdLen = len; wcmdLen = len;
} }
swprintf(wcmd, L"\"%s\"", wszApplicationName); swprintf(wcmd, L"\"%s\"", (LPWSTR)wszApplicationName);
if (sei_tmp.lpParameters[0]) if (sei_tmp.lpParameters[0])
{ {
strcatW(wcmd, L" "); strcatW(wcmd, L" ");
@ -2224,34 +2177,25 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei); retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
if (retval > 32) if (retval > 32)
{
HeapFree(GetProcessHeap(), 0, wszApplicationName);
if (wszParameters != parametersBuffer)
HeapFree(GetProcessHeap(), 0, wszParameters);
if (wszDir != dirBuffer)
HeapFree(GetProcessHeap(), 0, wszDir);
if (wcmd != wcmdBuffer)
HeapFree(GetProcessHeap(), 0, wcmd);
return TRUE; return TRUE;
}
} }
/* Else, try to find the executable */ /* Else, try to find the executable */
wcmd[0] = L'\0'; WCHAR wszKeyname[256];
CHeapPtr<WCHAR, CLocalAllocator> env;
wcmd[0] = UNICODE_NULL;
retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, wcmdLen, wszKeyname, &env, (LPITEMIDLIST)sei_tmp.lpIDList, sei_tmp.lpParameters); retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, wcmdLen, wszKeyname, &env, (LPITEMIDLIST)sei_tmp.lpIDList, sei_tmp.lpParameters);
if (retval > 32) /* Found */ if (retval > 32) /* Found */
{ {
retval = SHELL_quote_and_execute(wcmd, wszParameters, wszKeyname, retval = SHELL_quote_and_execute(wcmd, wszParameters, wszKeyname,
wszApplicationName, env, &sei_tmp, wszApplicationName, env, &sei_tmp,
sei, execfunc); sei, execfunc);
HeapFree(GetProcessHeap(), 0, env);
} }
else if (PathIsDirectoryW(lpFile)) else if (PathIsDirectoryW(lpFile))
{ {
WCHAR wExec[MAX_PATH]; WCHAR wExec[MAX_PATH];
WCHAR * lpQuotedFile = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (strlenW(lpFile) + 3)); CHeapPtr<WCHAR, CLocalAllocator> lpQuotedFile;
if (lpQuotedFile.Allocate(strlenW(lpFile) + 3))
if (lpQuotedFile)
{ {
retval = SHELL_FindExecutable(sei_tmp.lpDirectory, L"explorer", retval = SHELL_FindExecutable(sei_tmp.lpDirectory, L"explorer",
L"open", wExec, MAX_PATH, L"open", wExec, MAX_PATH,
@ -2263,9 +2207,7 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
wszKeyname, wszKeyname,
wszApplicationName, env, wszApplicationName, env,
&sei_tmp, sei, execfunc); &sei_tmp, sei, execfunc);
HeapFree(GetProcessHeap(), 0, env);
} }
HeapFree(GetProcessHeap(), 0, lpQuotedFile);
} }
else else
retval = 0; /* Out of memory */ retval = 0; /* Out of memory */
@ -2302,14 +2244,6 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName); do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
} }
HeapFree(GetProcessHeap(), 0, wszApplicationName);
if (wszParameters != parametersBuffer)
HeapFree(GetProcessHeap(), 0, wszParameters);
if (wszDir != dirBuffer)
HeapFree(GetProcessHeap(), 0, wszDir);
if (wcmd != wcmdBuffer)
HeapFree(GetProcessHeap(), 0, wcmd);
sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval); sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
return retval > 32; return retval > 32;