You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
8.5 KiB
222 lines
8.5 KiB
#include "CommandLine.h"
|
|
#include <malloc.h>
|
|
|
|
BOOL WINAPI MakeSureDirectoryPathExistsW(LPCWSTR DirPath);
|
|
|
|
DWORD WINAPI CheckCommandLineOptions(INT ArgC, LPWSTR* ArgVW) {
|
|
DWORD dwReturnFlags = 0;
|
|
INT i;
|
|
WCHAR* cp;
|
|
WCHAR wszInstallPath[MAX_PATH+1];
|
|
|
|
for (i = 1; i < ArgC && wcschr(L"/-",ArgVW[i][0]) != NULL; ++i) {
|
|
|
|
for (cp = &ArgVW[i][1]; *cp != L'\0'; ++cp) {
|
|
switch (towupper(*cp)) {
|
|
case L'U': {
|
|
HKEY hKey;
|
|
|
|
LONG lStatus = 0;
|
|
LONG lCreatedOrOpened = 0;
|
|
SET_FLAG(dwReturnFlags, FLAG_UNATTENDED_INSTALL);
|
|
|
|
// next param isn't a flag (or NULL), so it *must* be the path to install to
|
|
if ( (i+1 < ArgC) && wcschr(L"/-",ArgVW[i+1][0]) == NULL ) {
|
|
i++; // account for the parameter removed
|
|
|
|
SET_FLAG(dwReturnFlags, FLAG_UNATTENDED_PATH_PROVIDED);
|
|
StringCchCopyW(wszInstallPath, MAX_PATH+1, ArgVW[i]);
|
|
|
|
// make sure path ends in '\'
|
|
if (wszInstallPath[wcslen(wszInstallPath)]!=L'\\')
|
|
StringCchCatW(wszInstallPath,MAX_PATH+1,L"\\");
|
|
|
|
// make sure the directory exists!
|
|
if (! MakeSureDirectoryPathExistsW(wszInstallPath) ) {
|
|
SET_FLAG(dwReturnFlags, FLAG_FATAL_ERROR);
|
|
} else {
|
|
// Either create the regkey (if it doesn't exist) or open it (if it
|
|
// does exist). lCreatedOrOpened can be tested against
|
|
// REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY to determine which
|
|
// occurred.
|
|
lStatus = RegCreateKeyExW(SYMBOLS_REGKEY_ROOT,
|
|
SYMBOLS_REGKEY_PATH,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&lCreatedOrOpened);
|
|
|
|
if (lStatus != ERROR_SUCCESS) {
|
|
SET_FLAG(dwReturnFlags, FLAG_FATAL_ERROR);
|
|
} else {
|
|
// Write the value of the path to SYMBOLS_REGKEY
|
|
lStatus = RegSetValueExW( hKey, SYMBOLS_REGKEY, 0, REG_SZ, (BYTE*)wszInstallPath, ((wcslen(wszInstallPath) + 1) * sizeof(WCHAR)));
|
|
if (lStatus != ERROR_SUCCESS) {
|
|
SET_FLAG(dwReturnFlags, FLAG_FATAL_ERROR);
|
|
}
|
|
// close the regkey
|
|
lStatus = RegCloseKey( hKey );
|
|
if (lStatus != ERROR_SUCCESS) {
|
|
SET_FLAG(dwReturnFlags, FLAG_ERROR);
|
|
}
|
|
|
|
}
|
|
} // else ...
|
|
// couldn't set the path requests, so use what's
|
|
// already in the registry.
|
|
|
|
} // else ...
|
|
// no path provided, so don't set anything- setupapi will
|
|
// nicely use the existing key or default to the value
|
|
// specified in the INF
|
|
// StringCchCopyW(wszInstallPath, MAX_PATH+1, DEFAULT_INSTALL_PATH);
|
|
}
|
|
break;
|
|
|
|
case L'Q':
|
|
SET_FLAG(dwReturnFlags, FLAG_TOTALLY_QUIET);
|
|
break;
|
|
|
|
case L'?': // explicit fall through
|
|
case L'H': // explicit fall through
|
|
default:
|
|
SET_FLAG(dwReturnFlags, FLAG_USAGE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( IS_FLAG_SET(dwReturnFlags, FLAG_USAGE) ) {
|
|
WCHAR UsageBuffer[1024];
|
|
|
|
StringCchPrintfW(UsageBuffer,
|
|
sizeof(UsageBuffer)/sizeof(WCHAR),
|
|
L"Usage: %s [ /u [<path>] [/q] ]\n\n"
|
|
L"/u [<path>] \n"
|
|
L" Unattended install. If <path> is specified install\n"
|
|
L" symbols to <path>. If no path is specified, symbols\n"
|
|
L" are installed to the default location.\n"
|
|
L" NOTE: USING UNATTENDED INSTALL MEANS YOU\n"
|
|
L" HAVE READ AND AGREED TO THE END USER LICENSE\n"
|
|
L" AGREEMENT FOR THIS PRODUCT.\n"
|
|
L"/q\n"
|
|
L" Valid only when using unattended install. Prevents\n"
|
|
L" error messages from being display if unattended\n"
|
|
L" install fails.\n"
|
|
L"/?\n"
|
|
L" Show this dialog box.\n\n"
|
|
L"If no options are specified, the interactive installation\n"
|
|
L" is started.",
|
|
ArgVW[0]);
|
|
|
|
|
|
MessageBoxW( NULL,
|
|
UsageBuffer,
|
|
L"Microsoft Windows Symbols",
|
|
0 );
|
|
|
|
}
|
|
|
|
return(dwReturnFlags);
|
|
}
|
|
|
|
// Modified from MakeSureDirectoryPathExists from dbghelp.h
|
|
// The same caveats apply. (see MSDN)
|
|
BOOL WINAPI MakeSureDirectoryPathExistsW(LPCWSTR DirPath) {
|
|
LPWSTR p, DirCopy;
|
|
DWORD dw;
|
|
|
|
// Make a copy of the string for editing.
|
|
|
|
__try {
|
|
DirCopy = (LPWSTR)malloc((wcslen(DirPath) + 1) * sizeof(WCHAR));
|
|
|
|
if (!DirCopy) {
|
|
return FALSE;
|
|
}
|
|
|
|
StringCchCopyW(DirCopy, wcslen(DirPath)+1, DirPath);
|
|
|
|
p = DirCopy;
|
|
|
|
// If the second character in the path is "\", then this is a UNC
|
|
// path, and we should skip forward until we reach the 2nd \ in the path.
|
|
|
|
if ((*p == L'\\') && (*(p+1) == L'\\')) {
|
|
p++; // Skip over the first \ in the name.
|
|
p++; // Skip over the second \ in the name.
|
|
|
|
// Skip until we hit the first "\" (\\Server\).
|
|
|
|
while (*p && *p != L'\\') {
|
|
p = CharNextW(p);
|
|
}
|
|
|
|
// Advance over it.
|
|
|
|
if (*p) {
|
|
p++;
|
|
}
|
|
|
|
// Skip until we hit the second "\" (\\Server\Share\).
|
|
|
|
while (*p && *p != L'\\') {
|
|
p = CharNextW(p);
|
|
}
|
|
|
|
// Advance over it also.
|
|
|
|
if (*p) {
|
|
p++;
|
|
}
|
|
|
|
} else
|
|
// Not a UNC. See if it's <drive>:
|
|
if (*(p+1) == L':' ) {
|
|
|
|
p++;
|
|
p++;
|
|
|
|
// If it exists, skip over the root specifier
|
|
|
|
if (*p && (*p == L'\\')) {
|
|
p++;
|
|
}
|
|
}
|
|
|
|
while( *p ) {
|
|
if ( *p == '\\' ) {
|
|
*p = '\0';
|
|
dw = GetFileAttributesW(DirCopy);
|
|
// Nothing exists with this name. Try to make the directory name and error if unable to.
|
|
if ( dw == 0xffffffff ) {
|
|
if ( !CreateDirectoryW(DirCopy,NULL) ) {
|
|
if( GetLastError() != ERROR_ALREADY_EXISTS ) {
|
|
free(DirCopy);
|
|
return FALSE;
|
|
}
|
|
}
|
|
} else {
|
|
if ( (dw & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ) {
|
|
// Something exists with this name, but it's not a directory... Error
|
|
free(DirCopy);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
*p = L'\\';
|
|
}
|
|
p = CharNextW(p);
|
|
}
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
SetLastError( GetExceptionCode() );
|
|
free(DirCopy);
|
|
return(FALSE);
|
|
}
|
|
|
|
free(DirCopy);
|
|
return TRUE;
|
|
}
|