mirror of https://github.com/tongzx/nt5src
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.
950 lines
29 KiB
950 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sgmutil.c
|
|
|
|
Abstract:
|
|
|
|
Implements basic utilities used for source data gathering.
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 14-May-2000
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "v1p.h"
|
|
|
|
#define DBG_FOO "Foo"
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
#define USER_SHELL_FOLDERS \
|
|
DEFMAC(CSIDL_APPDATA, TEXT("AppData"), TEXT("CSIDL_APPDATA")) \
|
|
DEFMAC(CSIDL_APPDATA, TEXT("AppData"), TEXT("APPDATA")) \
|
|
DEFMAC(CSIDL_ADMINTOOLS, TEXT("Administrative Tools"), TEXT("CSIDL_ADMINTOOLS")) \
|
|
DEFMAC(CSIDL_ALTSTARTUP, TEXT("AltStartup"), TEXT("CSIDL_ALTSTARTUP")) \
|
|
DEFMAC(CSIDL_BITBUCKET, TEXT("RecycleBinFolder"), TEXT("CSIDL_BITBUCKET")) \
|
|
DEFMAC(CSIDL_CONTROLS, TEXT("ControlPanelFolder"), TEXT("CSIDL_CONTROLS")) \
|
|
DEFMAC(CSIDL_COOKIES, TEXT("Cookies"), TEXT("CSIDL_COOKIES")) \
|
|
DEFMAC(CSIDL_DESKTOP, TEXT("Desktop"), TEXT("CSIDL_DESKTOP")) \
|
|
DEFMAC(CSIDL_DESKTOPDIRECTORY, TEXT("Desktop"), TEXT("CSIDL_DESKTOPDIRECTORY")) \
|
|
DEFMAC(CSIDL_DRIVES, TEXT("DriveFolder"), TEXT("CSIDL_DRIVES")) \
|
|
DEFMAC(CSIDL_FAVORITES, TEXT("Favorites"), TEXT("CSIDL_FAVORITES")) \
|
|
DEFMAC(CSIDL_FONTS, TEXT("Fonts"), TEXT("CSIDL_FONTS")) \
|
|
DEFMAC(CSIDL_HISTORY, TEXT("History"), TEXT("CSIDL_HISTORY")) \
|
|
DEFMAC(CSIDL_INTERNET, TEXT("InternetFolder"), TEXT("CSIDL_INTERNET")) \
|
|
DEFMAC(CSIDL_INTERNET_CACHE, TEXT("Cache"), TEXT("CSIDL_INTERNET_CACHE")) \
|
|
DEFMAC(CSIDL_LOCAL_APPDATA, TEXT("Local AppData"), TEXT("CSIDL_LOCAL_APPDATA")) \
|
|
DEFMAC(CSIDL_MYPICTURES, TEXT("My Pictures"), TEXT("CSIDL_MYPICTURES")) \
|
|
DEFMAC(CSIDL_NETHOOD, TEXT("NetHood"), TEXT("CSIDL_NETHOOD")) \
|
|
DEFMAC(CSIDL_NETWORK, TEXT("NetworkFolder"), TEXT("CSIDL_NETWORK")) \
|
|
DEFMAC(CSIDL_PERSONAL, TEXT("Personal"), TEXT("CSIDL_PERSONAL")) \
|
|
DEFMAC(CSIDL_PROFILE, TEXT("Profile"), TEXT("CSIDL_PROFILE")) \
|
|
DEFMAC(CSIDL_PROGRAM_FILES, TEXT("ProgramFiles"), TEXT("CSIDL_PROGRAM_FILES")) \
|
|
DEFMAC(CSIDL_PROGRAM_FILES, TEXT("ProgramFiles"), TEXT("PROGRAMFILES")) \
|
|
DEFMAC(CSIDL_PROGRAM_FILES_COMMON, TEXT("CommonProgramFiles"), TEXT("CSIDL_PROGRAM_FILES_COMMON")) \
|
|
DEFMAC(CSIDL_PROGRAM_FILES_COMMON, TEXT("CommonProgramFiles"), TEXT("COMMONPROGRAMFILES")) \
|
|
DEFMAC(CSIDL_PROGRAMS, TEXT("Programs"), TEXT("CSIDL_PROGRAMS")) \
|
|
DEFMAC(CSIDL_RECENT, TEXT("Recent"), TEXT("CSIDL_RECENT")) \
|
|
DEFMAC(CSIDL_SENDTO, TEXT("SendTo"), TEXT("CSIDL_SENDTO")) \
|
|
DEFMAC(CSIDL_STARTMENU, TEXT("Start Menu"), TEXT("CSIDL_STARTMENU")) \
|
|
DEFMAC(CSIDL_STARTUP, TEXT("Startup"), TEXT("CSIDL_STARTUP")) \
|
|
DEFMAC(CSIDL_SYSTEM, TEXT("System"), TEXT("CSIDL_SYSTEM")) \
|
|
DEFMAC(CSIDL_TEMPLATES, TEXT("Templates"), TEXT("CSIDL_TEMPLATES")) \
|
|
DEFMAC(CSIDL_WINDOWS, TEXT("Windows"), TEXT("CSIDL_WINDOWS")) \
|
|
DEFMAC(CSIDL_MYDOCUMENTS, TEXT("My Documents"), TEXT("CSIDL_MYDOCUMENTS")) \
|
|
DEFMAC(CSIDL_MYMUSIC, TEXT("My Music"), TEXT("CSIDL_MYMUSIC")) \
|
|
DEFMAC(CSIDL_MYVIDEO, TEXT("My Video"), TEXT("CSIDL_MYVIDEO")) \
|
|
DEFMAC(CSIDL_SYSTEMX86, TEXT("SystemX86"), TEXT("CSIDL_SYSTEMX86")) \
|
|
DEFMAC(CSIDL_PROGRAM_FILESX86, TEXT("ProgramFilesX86"), TEXT("CSIDL_PROGRAM_FILESX86")) \
|
|
DEFMAC(CSIDL_PROGRAM_FILES_COMMONX86, TEXT("CommonProgramFilesX86"), TEXT("CSIDL_PROGRAM_FILES_COMMONX86")) \
|
|
DEFMAC(CSIDL_CONNECTIONS, TEXT("ConnectionsFolder"), TEXT("CSIDL_CONNECTIONS")) \
|
|
|
|
#define COMMON_SHELL_FOLDERS \
|
|
DEFMAC(CSIDL_COMMON_ADMINTOOLS, TEXT("Common Administrative Tools"), TEXT("CSIDL_COMMON_ADMINTOOLS")) \
|
|
DEFMAC(CSIDL_COMMON_ALTSTARTUP, TEXT("Common AltStartup"), TEXT("CSIDL_COMMON_ALTSTARTUP")) \
|
|
DEFMAC(CSIDL_COMMON_APPDATA, TEXT("Common AppData"), TEXT("CSIDL_COMMON_APPDATA")) \
|
|
DEFMAC(CSIDL_COMMON_DESKTOPDIRECTORY, TEXT("Common Desktop"), TEXT("CSIDL_COMMON_DESKTOPDIRECTORY")) \
|
|
DEFMAC(CSIDL_COMMON_DOCUMENTS, TEXT("Common Documents"), TEXT("CSIDL_COMMON_DOCUMENTS")) \
|
|
DEFMAC(CSIDL_COMMON_FAVORITES, TEXT("Common Favorites"), TEXT("CSIDL_COMMON_FAVORITES")) \
|
|
DEFMAC(CSIDL_COMMON_PROGRAMS, TEXT("Common Programs"), TEXT("CSIDL_COMMON_PROGRAMS")) \
|
|
DEFMAC(CSIDL_COMMON_STARTMENU, TEXT("Common Start Menu"), TEXT("CSIDL_COMMON_STARTMENU")) \
|
|
DEFMAC(CSIDL_COMMON_STARTUP, TEXT("Common Startup"), TEXT("CSIDL_COMMON_STARTUP")) \
|
|
DEFMAC(CSIDL_COMMON_TEMPLATES, TEXT("Common Templates"), TEXT("CSIDL_COMMON_TEMPLATES")) \
|
|
|
|
#define ENVIRONMENT_VARIABLES \
|
|
DEFMAC(TEXT("WINDIR")) \
|
|
DEFMAC(TEXT("SYSTEMROOT")) \
|
|
DEFMAC(TEXT("SYSTEM16")) \
|
|
DEFMAC(TEXT("SYSTEM32")) \
|
|
DEFMAC(TEXT("SYSTEM")) \
|
|
DEFMAC(TEXT("ALLUSERSPROFILE")) \
|
|
DEFMAC(TEXT("USERPROFILE")) \
|
|
DEFMAC(TEXT("PROFILESFOLDER")) \
|
|
DEFMAC(TEXT("APPDATA")) \
|
|
DEFMAC(TEXT("CSIDL_APPDATA")) \
|
|
DEFMAC(TEXT("CSIDL_ADMINTOOLS")) \
|
|
DEFMAC(TEXT("CSIDL_ALTSTARTUP")) \
|
|
DEFMAC(TEXT("CSIDL_BITBUCKET")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_ADMINTOOLS")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_ALTSTARTUP")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_APPDATA")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_DESKTOPDIRECTORY")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_DOCUMENTS")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_FAVORITES")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_PROGRAMS")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_STARTMENU")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_STARTUP")) \
|
|
DEFMAC(TEXT("CSIDL_COMMON_TEMPLATES")) \
|
|
DEFMAC(TEXT("CSIDL_CONTROLS")) \
|
|
DEFMAC(TEXT("CSIDL_COOKIES")) \
|
|
DEFMAC(TEXT("CSIDL_DESKTOP")) \
|
|
DEFMAC(TEXT("CSIDL_DESKTOPDIRECTORY")) \
|
|
DEFMAC(TEXT("CSIDL_DRIVES")) \
|
|
DEFMAC(TEXT("CSIDL_FAVORITES")) \
|
|
DEFMAC(TEXT("CSIDL_FONTS")) \
|
|
DEFMAC(TEXT("CSIDL_HISTORY")) \
|
|
DEFMAC(TEXT("CSIDL_INTERNET")) \
|
|
DEFMAC(TEXT("CSIDL_INTERNET_CACHE")) \
|
|
DEFMAC(TEXT("CSIDL_LOCAL_APPDATA")) \
|
|
DEFMAC(TEXT("CSIDL_MYPICTURES")) \
|
|
DEFMAC(TEXT("CSIDL_NETHOOD")) \
|
|
DEFMAC(TEXT("CSIDL_NETWORK")) \
|
|
DEFMAC(TEXT("CSIDL_PERSONAL")) \
|
|
DEFMAC(TEXT("CSIDL_PRINTERS")) \
|
|
DEFMAC(TEXT("CSIDL_PRINTHOOD")) \
|
|
DEFMAC(TEXT("CSIDL_PROFILE")) \
|
|
DEFMAC(TEXT("CSIDL_PROGRAM_FILES")) \
|
|
DEFMAC(TEXT("ProgramFiles")) \
|
|
DEFMAC(TEXT("CSIDL_PROGRAM_FILES_COMMON")) \
|
|
DEFMAC(TEXT("CommonProgramFiles")) \
|
|
DEFMAC(TEXT("CSIDL_PROGRAMS")) \
|
|
DEFMAC(TEXT("CSIDL_RECENT")) \
|
|
DEFMAC(TEXT("CSIDL_SENDTO")) \
|
|
DEFMAC(TEXT("CSIDL_STARTMENU")) \
|
|
DEFMAC(TEXT("CSIDL_STARTUP")) \
|
|
DEFMAC(TEXT("CSIDL_SYSTEM")) \
|
|
DEFMAC(TEXT("CSIDL_TEMPLATES")) \
|
|
DEFMAC(TEXT("CSIDL_WINDOWS")) \
|
|
DEFMAC(TEXT("CSIDL_MYDOCUMENTS")) \
|
|
DEFMAC(TEXT("CSIDL_MYMUSIC")) \
|
|
DEFMAC(TEXT("CSIDL_MYVIDEO")) \
|
|
DEFMAC(TEXT("CSIDL_SYSTEMX86")) \
|
|
DEFMAC(TEXT("CSIDL_PROGRAM_FILESX86")) \
|
|
DEFMAC(TEXT("CSIDL_PROGRAM_FILES_COMMONX86")) \
|
|
DEFMAC(TEXT("CSIDL_CONNECTIONS")) \
|
|
DEFMAC(TEXT("TEMP")) \
|
|
DEFMAC(TEXT("TMP")) \
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
/*++
|
|
|
|
The shell folder functions here are duplicates of the RAS code. This is not
|
|
a good solution (we have two copies of the same code), but the designed
|
|
solution requires engine scope support. Scopes are the mechanism in which
|
|
major groups of data are separated from each other, such as the separation
|
|
of multiple users. A scope provides properties that affect objects within
|
|
the scope. For example, a user scope has properties such as domain name,
|
|
profile path, sid, and so on.
|
|
|
|
In order not to duplicate this code but still maintain modularity and system
|
|
independence, a scope module is needed for users. So instead of the code
|
|
below, the code would be something like
|
|
|
|
property = IsmGetScopeProperty ("userprofile");
|
|
|
|
This will be implemented if we want to (A) support multiple scopes, (B)
|
|
eliminate physical system access in non-type modules, or (C) clean up this
|
|
duplicated code.
|
|
|
|
--*/
|
|
|
|
typedef HRESULT (WINAPI SHGETFOLDERPATH)(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, PTSTR pszPath);
|
|
typedef SHGETFOLDERPATH * PSHGETFOLDERPATH;
|
|
|
|
HANDLE
|
|
pGetShFolderLib (
|
|
VOID
|
|
)
|
|
{
|
|
static HANDLE lib;
|
|
|
|
if (lib) {
|
|
return lib;
|
|
}
|
|
|
|
lib = LoadLibrary (TEXT("shfolder.dll"));
|
|
if (!lib) {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_SHFOLDER_LOAD_ERROR));
|
|
}
|
|
|
|
return lib;
|
|
}
|
|
|
|
PTSTR
|
|
pFindSfPath (
|
|
IN PCTSTR FolderStr,
|
|
IN BOOL UserFolder
|
|
)
|
|
{
|
|
HKEY key;
|
|
REGSAM prevMode;
|
|
PCTSTR data;
|
|
PCTSTR result = NULL;
|
|
|
|
if (!result) {
|
|
if (UserFolder) {
|
|
prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
|
|
key = OpenRegKeyStr (TEXT("HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"));
|
|
SetRegOpenAccessMode (prevMode);
|
|
} else {
|
|
prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
|
|
key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"));
|
|
SetRegOpenAccessMode (prevMode);
|
|
}
|
|
|
|
if (key) {
|
|
data = GetRegValueString (key, FolderStr);
|
|
|
|
if (data) {
|
|
result = DuplicatePathString (data, 0);
|
|
FreeAlloc (data);
|
|
}
|
|
CloseRegKey (key);
|
|
}
|
|
}
|
|
|
|
if (!result) {
|
|
if (UserFolder) {
|
|
prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
|
|
key = OpenRegKeyStr (TEXT("HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"));
|
|
SetRegOpenAccessMode (prevMode);
|
|
} else {
|
|
prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
|
|
key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"));
|
|
SetRegOpenAccessMode (prevMode);
|
|
}
|
|
|
|
if (key) {
|
|
data = GetRegValueString (key, FolderStr);
|
|
|
|
if (data) {
|
|
result = DuplicatePathString (data, 0);
|
|
FreeAlloc (data);
|
|
}
|
|
CloseRegKey (key);
|
|
}
|
|
}
|
|
|
|
return (PTSTR) result;
|
|
}
|
|
|
|
PCTSTR
|
|
GetShellFolderPath (
|
|
IN INT Folder,
|
|
IN PCTSTR FolderStr,
|
|
IN BOOL UserFolder,
|
|
OUT PTSTR Buffer
|
|
)
|
|
{
|
|
HRESULT result;
|
|
LPITEMIDLIST pidl;
|
|
BOOL b;
|
|
LPMALLOC mallocFn;
|
|
HANDLE lib;
|
|
PSHGETFOLDERPATH shGetFolderPath;
|
|
PCTSTR sfPath = NULL;
|
|
PCTSTR expandedPath = NULL;
|
|
PTSTR endPtr = NULL;
|
|
TCHAR currUserProfile[MAX_TCHAR_PATH];
|
|
MIG_USERDATA userData;
|
|
|
|
result = SHGetMalloc (&mallocFn);
|
|
if (result != S_OK) {
|
|
return NULL;
|
|
}
|
|
|
|
if (FolderStr) {
|
|
|
|
//
|
|
// First try to find this in Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
|
|
//
|
|
sfPath = pFindSfPath (FolderStr, UserFolder);
|
|
|
|
if (sfPath && *sfPath) {
|
|
//
|
|
// We found it.
|
|
//
|
|
StringCopyTcharCount (Buffer, sfPath, MAX_PATH);
|
|
expandedPath = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, sfPath, NULL);
|
|
FreePathString (sfPath);
|
|
sfPath = NULL;
|
|
if (expandedPath && *expandedPath) {
|
|
StringCopyTcharCount (Buffer, expandedPath, MAX_PATH);
|
|
}
|
|
if (expandedPath) {
|
|
IsmReleaseMemory (expandedPath);
|
|
}
|
|
|
|
if (IsmGetMappedUserData (&userData)) {
|
|
// we have a mapped user, try to build it's default shell folder location
|
|
GetUserProfileRootPath (currUserProfile);
|
|
|
|
if (StringIMatch (currUserProfile, Buffer)) {
|
|
StringCopyTcharCount (Buffer, userData.UserProfileRoot, MAX_PATH);
|
|
} else {
|
|
AppendWack (currUserProfile);
|
|
|
|
if (StringIMatchTcharCount (currUserProfile, Buffer, TcharCount (currUserProfile))) {
|
|
|
|
endPtr = Buffer + TcharCount (currUserProfile);
|
|
sfPath = JoinPaths (userData.UserProfileRoot, endPtr);
|
|
StringCopyTcharCount (Buffer, sfPath, MAX_PATH);
|
|
FreePathString (sfPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
return Buffer;
|
|
}
|
|
if (sfPath) {
|
|
FreePathString (sfPath);
|
|
}
|
|
|
|
lib = pGetShFolderLib ();
|
|
|
|
if (lib) {
|
|
#ifdef UNICODE
|
|
(FARPROC) shGetFolderPath = GetProcAddress (lib, "SHGetFolderPathW");
|
|
#else
|
|
(FARPROC) shGetFolderPath = GetProcAddress (lib, "SHGetFolderPathA");
|
|
#endif
|
|
if (shGetFolderPath) {
|
|
result = shGetFolderPath (NULL, Folder, NULL, 1, Buffer);
|
|
if (result != S_OK) {
|
|
return NULL;
|
|
}
|
|
expandedPath = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, Buffer, NULL);
|
|
if (expandedPath && *expandedPath) {
|
|
StringCopyTcharCount (Buffer, expandedPath, MAX_PATH);
|
|
}
|
|
if (expandedPath) {
|
|
IsmReleaseMemory (expandedPath);
|
|
expandedPath = NULL;
|
|
}
|
|
|
|
if (IsmGetMappedUserData (&userData)) {
|
|
// we have a mapped user, try to build it's default shell folder location
|
|
GetUserProfileRootPath (currUserProfile);
|
|
|
|
if (StringIMatch (currUserProfile, Buffer)) {
|
|
StringCopyTcharCount (Buffer, userData.UserProfileRoot, MAX_PATH);
|
|
} else {
|
|
AppendWack (currUserProfile);
|
|
|
|
if (StringIMatchTcharCount (currUserProfile, Buffer, TcharCount (currUserProfile))) {
|
|
|
|
endPtr = Buffer + TcharCount (currUserProfile);
|
|
sfPath = JoinPaths (userData.UserProfileRoot, endPtr);
|
|
StringCopyTcharCount (Buffer, sfPath, MAX_PATH);
|
|
FreePathString (sfPath);
|
|
}
|
|
}
|
|
|
|
return Buffer;
|
|
|
|
} else {
|
|
// no mapped user, use the current user's path
|
|
result = shGetFolderPath (NULL, Folder, NULL, 0, Buffer);
|
|
}
|
|
if (result != S_OK) {
|
|
return NULL;
|
|
}
|
|
expandedPath = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, Buffer, NULL);
|
|
if (expandedPath && *expandedPath) {
|
|
StringCopyTcharCount (Buffer, expandedPath, MAX_PATH);
|
|
}
|
|
if (expandedPath) {
|
|
IsmReleaseMemory (expandedPath);
|
|
expandedPath = NULL;
|
|
}
|
|
return Buffer;
|
|
} else {
|
|
result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
|
|
}
|
|
} else {
|
|
result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
|
|
}
|
|
|
|
if (result != S_OK) {
|
|
return NULL;
|
|
}
|
|
|
|
b = SHGetPathFromIDList (pidl, Buffer);
|
|
} else {
|
|
|
|
result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
|
|
|
|
if (result != S_OK) {
|
|
return NULL;
|
|
}
|
|
|
|
b = SHGetPathFromIDList (pidl, Buffer);
|
|
}
|
|
|
|
IMalloc_Free (mallocFn, pidl);
|
|
|
|
return b ? Buffer : NULL;
|
|
}
|
|
|
|
|
|
PCTSTR
|
|
GetAllUsersProfilePath (
|
|
OUT PTSTR Buffer
|
|
)
|
|
{
|
|
HKEY key;
|
|
REGSAM prevMode;
|
|
PCTSTR data;
|
|
PCTSTR expData;
|
|
|
|
prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
|
|
key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"));
|
|
SetRegOpenAccessMode (prevMode);
|
|
|
|
if (key) {
|
|
|
|
data = GetRegValueString (key, TEXT("ProfilesDirectory"));
|
|
|
|
if (data) {
|
|
expData = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, data, NULL);
|
|
StringCopyByteCount (Buffer, expData, MAX_PATH);
|
|
IsmReleaseMemory (expData);
|
|
FreeAlloc (data);
|
|
} else {
|
|
GetWindowsDirectory (Buffer, MAX_PATH);
|
|
StringCopy (AppendWack (Buffer), TEXT("Profiles"));
|
|
}
|
|
|
|
data = GetRegValueString (key, TEXT("AllUsersProfile"));
|
|
|
|
if (data) {
|
|
StringCopy (AppendWack (Buffer), data);
|
|
FreeAlloc (data);
|
|
} else {
|
|
StringCopy (AppendWack (Buffer), TEXT("All Users"));
|
|
}
|
|
|
|
CloseRegKey (key);
|
|
return Buffer;
|
|
}
|
|
|
|
GetWindowsDirectory (Buffer, MAX_PATH);
|
|
return Buffer;
|
|
}
|
|
|
|
PCTSTR
|
|
GetProfilesFolderPath (
|
|
OUT PTSTR Buffer
|
|
)
|
|
{
|
|
HKEY key;
|
|
REGSAM prevMode;
|
|
PCTSTR data;
|
|
PCTSTR expData;
|
|
|
|
prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
|
|
key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"));
|
|
SetRegOpenAccessMode (prevMode);
|
|
|
|
if (key) {
|
|
|
|
data = GetRegValueString (key, TEXT("ProfilesDirectory"));
|
|
|
|
if (data) {
|
|
expData = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, data, NULL);
|
|
StringCopyByteCount (Buffer, expData, MAX_PATH);
|
|
IsmReleaseMemory (expData);
|
|
FreeAlloc (data);
|
|
} else {
|
|
GetWindowsDirectory (Buffer, MAX_PATH);
|
|
StringCopy (AppendWack (Buffer), TEXT("Profiles"));
|
|
}
|
|
|
|
CloseRegKey (key);
|
|
return Buffer;
|
|
}
|
|
|
|
GetWindowsDirectory (Buffer, MAX_PATH);
|
|
return Buffer;
|
|
}
|
|
|
|
PCTSTR
|
|
GetUserProfileRootPath (
|
|
OUT PTSTR Buffer
|
|
)
|
|
{
|
|
HKEY key;
|
|
REGSAM prevMode;
|
|
PDWORD data;
|
|
DWORD size;
|
|
|
|
//
|
|
// For Win2k and higher, use the shell
|
|
//
|
|
|
|
if (GetShellFolderPath (CSIDL_PROFILE, NULL, FALSE, Buffer)) {
|
|
return Buffer;
|
|
}
|
|
|
|
//
|
|
// For NT 4, use the environment
|
|
//
|
|
|
|
if (GetEnvironmentVariable (TEXT("USERPROFILE"), Buffer, MAX_PATH)) {
|
|
return Buffer;
|
|
}
|
|
|
|
//
|
|
// For Win9x, are profiles enabled? If so, return %windir%\profiles\%user%.
|
|
// If not, return %windir%.
|
|
//
|
|
|
|
GetWindowsDirectory (Buffer, MAX_PATH);
|
|
|
|
prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
|
|
key = OpenRegKeyStr (TEXT("HKLM\\Network\\Logon"));
|
|
SetRegOpenAccessMode (prevMode);
|
|
if (key) {
|
|
|
|
data = GetRegValueDword (key, TEXT("UserProfiles"));
|
|
|
|
if (data && *data) {
|
|
StringCat (Buffer, TEXT("\\Profiles\\"));
|
|
|
|
size = MAX_PATH;
|
|
GetUserName (GetEndOfString (Buffer), &size);
|
|
|
|
FreeAlloc (data);
|
|
}
|
|
|
|
CloseRegKey (key);
|
|
}
|
|
|
|
return Buffer;
|
|
}
|
|
|
|
|
|
PCTSTR
|
|
IsValidUncPath (
|
|
IN PCTSTR Path
|
|
)
|
|
{
|
|
BOOL needNonWack = FALSE;
|
|
BOOL wackRequired = TRUE;
|
|
INT wacks = 0;
|
|
|
|
while (*Path) {
|
|
|
|
if (_tcsnextc (Path) == TEXT('\\')) {
|
|
|
|
if (needNonWack) {
|
|
break;
|
|
}
|
|
|
|
wacks++;
|
|
if (wacks != 1) {
|
|
needNonWack = TRUE;
|
|
wackRequired = FALSE;
|
|
}
|
|
|
|
Path++;
|
|
|
|
} else {
|
|
//
|
|
// Note: it would be nice to validate the non-wack characters against the
|
|
// legal unc charset
|
|
//
|
|
|
|
if (needNonWack) {
|
|
if (wacks == 3) {
|
|
//
|
|
// Found \\x\x syntax; it's a UNC path
|
|
//
|
|
|
|
do {
|
|
Path = _tcsinc (Path);
|
|
} while (*Path && _tcsnextc (Path) != TEXT('\\'));
|
|
|
|
MYASSERT (*Path == 0 || *Path == TEXT('\\'));
|
|
return Path;
|
|
}
|
|
|
|
needNonWack = FALSE;
|
|
}
|
|
|
|
if (wackRequired) {
|
|
break;
|
|
}
|
|
|
|
Path = _tcsinc (Path);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsValidFileSpec (
|
|
IN PCTSTR FileSpec
|
|
)
|
|
{
|
|
CHARTYPE ch;
|
|
BOOL result = TRUE;
|
|
|
|
for (;;) {
|
|
ch = (CHARTYPE) _tcsnextc (FileSpec);
|
|
if (ch == TEXT('*')) {
|
|
//
|
|
// Really can't say what the validity is!
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
if (!_istalpha (ch) && ch != TEXT('?')) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
ch = (CHARTYPE) _tcsnextc (FileSpec + 1);
|
|
if (ch == TEXT('*')) {
|
|
break;
|
|
}
|
|
|
|
if (ch != TEXT(':') && ch != TEXT('?')) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
ch = (CHARTYPE) _tcsnextc (FileSpec + 2);
|
|
|
|
if (ch == 0) {
|
|
// this is something like "d:", it's valid
|
|
break;
|
|
}
|
|
|
|
if (ch == TEXT('*')) {
|
|
break;
|
|
}
|
|
|
|
if (ch != TEXT('\\') && ch != TEXT('?')) {
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (!result) {
|
|
result = (IsValidUncPath (FileSpec) != NULL);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
VOID
|
|
pSetEnvironmentVar (
|
|
IN PMAPSTRUCT Map,
|
|
IN PMAPSTRUCT UndefMap, OPTIONAL
|
|
IN BOOL MapSourceToDest,
|
|
IN PCTSTR VariableName,
|
|
IN PCTSTR VariableData OPTIONAL
|
|
)
|
|
{
|
|
TCHAR encodedVariableName[128];
|
|
TCHAR buffer[MAX_TCHAR_PATH];
|
|
PCTSTR undefText;
|
|
|
|
//
|
|
// VariableData is NULL when VariableName is not present on the machine
|
|
//
|
|
|
|
if (MapSourceToDest) {
|
|
|
|
//
|
|
// MapSourceToDest tells us to map a source path (c:\windows) to
|
|
// a destination path (d:\winnt).
|
|
//
|
|
|
|
if (VariableData) {
|
|
if (IsmGetEnvironmentString (
|
|
PLATFORM_SOURCE,
|
|
S_SYSENVVAR_GROUP,
|
|
VariableName,
|
|
buffer,
|
|
ARRAYSIZE(buffer),
|
|
NULL
|
|
)) {
|
|
AddStringMappingPair (Map, buffer, VariableData);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// MapSourceToDest is FALSE when we want to map environment variables
|
|
// to the actual path.
|
|
//
|
|
|
|
//
|
|
// VariableName length is hard-coded, so we know it does not exceed our
|
|
// buffer
|
|
//
|
|
|
|
wsprintf (encodedVariableName, TEXT("%%%s%%"), VariableName);
|
|
|
|
if (VariableData) {
|
|
|
|
IsmSetEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, VariableName, VariableData);
|
|
AddStringMappingPair (Map, encodedVariableName, VariableData);
|
|
|
|
} else if (UndefMap) {
|
|
|
|
//
|
|
// If no variable data, then put environment variable in the
|
|
// "undefined" variable mapping
|
|
//
|
|
|
|
undefText = JoinTextEx (NULL, TEXT("--> "), TEXT(" <--"), encodedVariableName, 0, NULL);
|
|
AddStringMappingPair (UndefMap, encodedVariableName, undefText);
|
|
FreeText (undefText);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
AddRemappingEnvVar (
|
|
IN PMAPSTRUCT Map,
|
|
IN PMAPSTRUCT ReMap,
|
|
IN PMAPSTRUCT UndefMap, OPTIONAL
|
|
IN PCTSTR VariableName,
|
|
IN PCTSTR VariableData
|
|
)
|
|
{
|
|
pSetEnvironmentVar (Map, UndefMap, FALSE, VariableName, VariableData);
|
|
pSetEnvironmentVar (ReMap, UndefMap, TRUE, VariableName, VariableData);
|
|
}
|
|
|
|
|
|
VOID
|
|
SetIsmEnvironmentFromPhysicalMachine (
|
|
IN PMAPSTRUCT Map,
|
|
IN BOOL MapSourceToDest,
|
|
IN PMAPSTRUCT UndefMap OPTIONAL
|
|
)
|
|
{
|
|
TCHAR dir[MAX_TCHAR_PATH];
|
|
PCTSTR path;
|
|
PTSTR p;
|
|
MIG_USERDATA userData;
|
|
BOOL mappedUser = FALSE;
|
|
|
|
mappedUser = IsmGetMappedUserData (&userData);
|
|
|
|
//
|
|
// Prepare ISM environment variables. The ones added last have the highest priority when
|
|
// two or more variables map to the same path.
|
|
//
|
|
|
|
//
|
|
// ...user profile
|
|
//
|
|
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("ALLUSERSPROFILE"), GetAllUsersProfilePath (dir));
|
|
|
|
if (mappedUser) {
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("USERPROFILE"), userData.UserProfileRoot);
|
|
} else {
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("USERPROFILE"), GetUserProfileRootPath (dir));
|
|
}
|
|
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("PROFILESFOLDER"), GetProfilesFolderPath (dir));
|
|
|
|
//
|
|
// ...temp dir
|
|
//
|
|
|
|
if (GetTempPath (MAX_PATH, dir)) {
|
|
p = (PTSTR) FindLastWack (dir);
|
|
if (p) {
|
|
if (p[1] == 0) {
|
|
*p = 0;
|
|
}
|
|
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("TEMP"), dir);
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("TMP"), dir);
|
|
}
|
|
}
|
|
|
|
//
|
|
// ...windows directory env variable
|
|
//
|
|
|
|
GetWindowsDirectory (dir, ARRAYSIZE(dir));
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("WINDIR"), dir);
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEMROOT"), dir);
|
|
|
|
//
|
|
// ...16-bit system directory. We invent SYSTEM16 and SYSTEM32 for use
|
|
// in scripts.
|
|
//
|
|
|
|
path = JoinPaths (dir, TEXT("system"));
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM16"), path);
|
|
FreePathString (path);
|
|
|
|
path = JoinPaths (dir, TEXT("system32"));
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM32"), path);
|
|
FreePathString (path);
|
|
|
|
//
|
|
// ...platform-specific system directory
|
|
//
|
|
|
|
GetSystemDirectory (dir, ARRAYSIZE(dir));
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM"), dir);
|
|
|
|
//
|
|
// ...shell folders -- we invent all variables with the CSIDL_ prefix
|
|
//
|
|
|
|
#define DEFMAC(id,folder_str,var_name) \
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, var_name, \
|
|
GetShellFolderPath (id, folder_str, TRUE, dir));
|
|
|
|
USER_SHELL_FOLDERS
|
|
|
|
#undef DEFMAC
|
|
|
|
|
|
#define DEFMAC(id,folder_str,var_name) \
|
|
pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, var_name, \
|
|
GetShellFolderPath (id, folder_str, FALSE, dir));
|
|
|
|
COMMON_SHELL_FOLDERS
|
|
|
|
#undef DEFMAC
|
|
}
|
|
|
|
VOID
|
|
pTransferEnvPath (
|
|
IN PCTSTR IsmVariableName,
|
|
IN PMAPSTRUCT DirectMap,
|
|
IN PMAPSTRUCT ReverseMap,
|
|
IN PMAPSTRUCT UndefMap
|
|
)
|
|
{
|
|
TCHAR dir[MAX_TCHAR_PATH];
|
|
TCHAR encodedVariableName[128];
|
|
PCTSTR undefText;
|
|
|
|
wsprintf (encodedVariableName, TEXT("%%%s%%"), IsmVariableName);
|
|
|
|
if (IsmGetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, IsmVariableName, dir, sizeof(dir)/sizeof((dir)[0]), NULL)) {
|
|
if (DirectMap) {
|
|
AddStringMappingPair (DirectMap, encodedVariableName, dir);
|
|
}
|
|
if (ReverseMap) {
|
|
AddStringMappingPair (ReverseMap, dir, encodedVariableName);
|
|
}
|
|
} else {
|
|
undefText = JoinTextEx (NULL, TEXT("--> "), TEXT(" <--"), encodedVariableName, 0, NULL);
|
|
if (UndefMap) {
|
|
AddStringMappingPair (UndefMap, encodedVariableName, undefText);
|
|
}
|
|
FreeText (undefText);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
SetIsmEnvironmentFromVirtualMachine (
|
|
IN PMAPSTRUCT DirectMap,
|
|
IN PMAPSTRUCT ReverseMap,
|
|
IN PMAPSTRUCT UndefMap
|
|
)
|
|
{
|
|
//
|
|
// Need to transfer ISM environment into our string mapping
|
|
//
|
|
|
|
#define DEFMAC(name) pTransferEnvPath(name, DirectMap, ReverseMap, UndefMap);
|
|
|
|
ENVIRONMENT_VARIABLES
|
|
|
|
#undef DEFMAC
|
|
}
|
|
|