337 lines
11 KiB
C
337 lines
11 KiB
C
/*++
|
|
migrate.c
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
|
|
This module performs Windows 95 to Windows NT fax migration.
|
|
Specifically, this file contains the Windows NT side of migration...
|
|
|
|
Author:
|
|
|
|
Brian Dewey (t-briand) 1997-7-14
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <setupapi.h>
|
|
#include <wchar.h>
|
|
#include <tchar.h>
|
|
#include "migrate.h" // Contains prototypes & version information.
|
|
#include "debug.h" // Includes TRACE definition
|
|
#include "resource.h" // Resources.
|
|
|
|
// ------------------------------------------------------------
|
|
// Global data
|
|
|
|
// Wide names of the working & source directories.
|
|
static WCHAR lpWorkingDir[MAX_PATH],
|
|
lpSourceDir[MAX_PATH];
|
|
HINSTANCE hinstMigDll;
|
|
|
|
// ------------------------------------------------------------
|
|
// Prototypes
|
|
static BOOL CreateKeyAndValue(HKEY hRoot, LPWSTR szSubKey, LPWSTR szName, LPWSTR szDefaultValue);
|
|
|
|
BOOL WINAPI
|
|
DllEntryPoint(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
|
|
{
|
|
if(dwReason == DLL_PROCESS_ATTACH) {
|
|
TRACE((TEXT("Migration DLL attached.\r\n")));
|
|
hinstMigDll = hinstDll;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// InitializeNT
|
|
//
|
|
// This routine performs NT-side initialization.
|
|
//
|
|
// Parameters:
|
|
// Documented below.
|
|
//
|
|
// Returns:
|
|
// ERROR_SUCCESS.
|
|
//
|
|
// Author:
|
|
// Brian Dewey (t-briand) 1997-7-14
|
|
LONG
|
|
CALLBACK
|
|
InitializeNT(
|
|
IN LPCWSTR WorkingDirectory, // Working directory for temporary files.
|
|
IN LPCWSTR SourceDirectory, // Directory of winNT source.
|
|
LPVOID Reserved // It's reserved.
|
|
)
|
|
{
|
|
TRACE((TEXT("Fax Migration:NT Side Initialized.\r\n")));
|
|
wcscpy(lpWorkingDir, WorkingDirectory);
|
|
wcscpy(lpSourceDir, SourceDirectory);
|
|
return ERROR_SUCCESS; // A very confused return value.
|
|
}
|
|
|
|
|
|
// MigrateUserNT
|
|
//
|
|
// Sets up user information.
|
|
//
|
|
// Parameters:
|
|
// Documented below.
|
|
//
|
|
// Returns:
|
|
// ERROR_SUCCESS.
|
|
//
|
|
// Author:
|
|
// Brian Dewey (t-briand) 1997-7-14
|
|
LONG
|
|
CALLBACK
|
|
MigrateUserNT(
|
|
IN HINF UnattendInfHandle, // Access to the unattend.txt file.
|
|
IN HKEY UserRegHandle, // Handle to registry settings for user.
|
|
IN LPCWSTR UserName, // Name of the user.
|
|
LPVOID Reserved
|
|
)
|
|
{
|
|
// our task: copy entries from szInfFileName to the registry.
|
|
LPTSTR lpNTOptions = TEXT("Software\\Microsoft\\Fax\\UserInfo");
|
|
HKEY hReg; // Registry key for user.
|
|
LPCTSTR alpKeys[] = { // This array defines what keys will be
|
|
TEXT("Address"), // copied from faxuser.ini into the registry.
|
|
TEXT("Company"),
|
|
TEXT("Department"),
|
|
TEXT("FaxNumber"),
|
|
TEXT("FullName"),
|
|
TEXT("HomePhone"),
|
|
TEXT("Mailbox"),
|
|
TEXT("Office"),
|
|
TEXT("OfficePhone"),
|
|
TEXT("Title")
|
|
};
|
|
UINT iCount, iMax; // used for looping through all the sections.
|
|
UINT i; // Used for converting doubled ';' to CR/LF pairs.
|
|
TCHAR szValue[MAX_PATH];
|
|
TCHAR szInfFileNameRes[MAX_PATH];
|
|
TCHAR szUser[MAX_PATH]; // TCHAR representation of the user name.
|
|
LONG lError; // Holds a returned error code.
|
|
|
|
if(UserName == NULL) {
|
|
// NULL means the logon user.
|
|
_tcscpy(szUser, lpLogonUser);// Get the logon user name for faxuser.ini
|
|
} else {
|
|
#ifdef _UNICODE
|
|
// If this is a unicode compile, UserName and szUser are the same. Just
|
|
// copy one to the other.
|
|
wcscpy(szUser, UserName);
|
|
#else
|
|
// We need to convert the wide UserName to the narrow szUser.
|
|
WideCharToMultiByte(
|
|
CP_ACP, // Convert to ANSI.
|
|
0, // No flags.
|
|
UserName, // The wide char set.
|
|
-1, // Null-terminated string.
|
|
szUser, // Holds the converted string.
|
|
sizeof(szUser), // Size of this buffer...
|
|
NULL, // Use default unmappable character.
|
|
NULL // I don't need to know if I used the default.
|
|
);
|
|
#endif // _UNICODE
|
|
}
|
|
|
|
TRACE((TEXT("(MigrateUserNT):Migrating user '%s'.\r\n"), szUser));
|
|
|
|
if(RegOpenKeyEx(UserRegHandle,
|
|
lpNTOptions, // Open this subkey.
|
|
0, // Reserved.
|
|
KEY_WRITE, // We want write permission.
|
|
&hReg) != ERROR_SUCCESS) {
|
|
// All I'm allowed to do is return obscure error codes...
|
|
// However, unless there's a hardware failure, I'm supposed to say
|
|
// everything's OK.
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
iMax = sizeof(alpKeys) / sizeof(LPCTSTR);
|
|
|
|
_stprintf(szInfFileNameRes, TEXT("%s\\migrate.inf"), lpWorkingDir);
|
|
|
|
ExpandEnvironmentStrings(szInfFileNameRes, szInfFileName, MAX_PATH);
|
|
|
|
TRACE((TEXT("Reading from file %s.\r\n"), szInfFileName));
|
|
for(iCount = 0; iCount < iMax; iCount++) {
|
|
GetPrivateProfileString(
|
|
szUser,
|
|
alpKeys[iCount],
|
|
TEXT(""),
|
|
szValue,
|
|
sizeof(szValue),
|
|
szInfFileName
|
|
);
|
|
// If there was a CR/LF pair, the w95 side of things converted it
|
|
// to a doubled semicolon. So I'm going to look for doubled semicolons
|
|
// and convert them to CR/LF pairs.
|
|
i = 0;
|
|
while(szValue[i] != _T('\0')) {
|
|
if((szValue[i] == _T(';')) && (szValue[i+1] == _T(';'))) {
|
|
// Found a doubled semicolon.
|
|
szValue[i] = '\r';
|
|
szValue[i+1] = '\n';
|
|
TRACE((TEXT("Doing newline translation.\r\n")));
|
|
}
|
|
i++;
|
|
}
|
|
lError = RegSetValueEx(hReg,
|
|
alpKeys[iCount],
|
|
0,
|
|
REG_SZ,
|
|
szValue,
|
|
_tcslen(szValue)+1);
|
|
if(lError != ERROR_SUCCESS) {
|
|
TRACE((TEXT("Error in RegSetValueEx():%x\r\n"), lError));
|
|
return lError;
|
|
}
|
|
TRACE((TEXT("%s = %s\r\n"), alpKeys[iCount], szValue));
|
|
}
|
|
RegCloseKey(hReg);
|
|
return ERROR_SUCCESS; // A very confused return value.
|
|
}
|
|
|
|
|
|
// MigrateSystemNT
|
|
//
|
|
// Updates the system registry to associate 'awdvstub.exe' with the
|
|
// AWD extension.
|
|
//
|
|
// Parameters:
|
|
// Documented below.
|
|
//
|
|
// Returns:
|
|
// ERROR_SUCCESS.
|
|
//
|
|
// Author:
|
|
// Brian Dewey (t-briand) 1997-7-14
|
|
LONG
|
|
CALLBACK
|
|
MigrateSystemNT(
|
|
IN HINF UnattendInfHandle, // Access to the unattend.txt file.
|
|
LPVOID Reserved
|
|
)
|
|
{
|
|
WCHAR szExeFileName[MAX_PATH];
|
|
WCHAR szWindowsDir[MAX_PATH];
|
|
WCHAR szDestFile[MAX_PATH];
|
|
WCHAR szOpenCommand[MAX_PATH + 16];
|
|
WCHAR szConvertCommand[MAX_PATH + 16]; // "*" /c "%1"
|
|
|
|
|
|
// first, copy 'awdvstub.exe' to %SystemRoot%\system32.
|
|
GetWindowsDirectoryW(szWindowsDir, MAX_PATH);
|
|
swprintf(szExeFileName, L"%s\\%s", lpWorkingDir, L"awdvstub.exe");
|
|
swprintf(szDestFile, L"%s\\system32\\%s", szWindowsDir, L"awdvstub.exe");
|
|
if(!CopyFileW(szExeFileName,
|
|
szDestFile,
|
|
FALSE)) {
|
|
TRACE((TEXT("Fax:MigrateSystemNT:Copy file failed.\r\n")));
|
|
} else {
|
|
TRACE((TEXT("Fax:MigrateSystemNT:Copy file succeeded.\r\n")));
|
|
}
|
|
|
|
// Generate the command lines.
|
|
swprintf(szOpenCommand, L"\"%s\" \"%%1\"", szDestFile);
|
|
swprintf(szConvertCommand, L"\"%s\" /c \"%%1\"", szDestFile);
|
|
|
|
// Now, update the registry.
|
|
CreateKeyAndValue(HKEY_CLASSES_ROOT, NULL, L".awd", L"awdfile");
|
|
CreateKeyAndValue(HKEY_CLASSES_ROOT, NULL, L"awdfile", L"Windows 95 Fax File (obsolete)");
|
|
CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile", L"shell", NULL);
|
|
CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile\\shell", L"open", NULL);
|
|
CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile\\shell\\open", L"command", szOpenCommand);
|
|
CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile\\shell", L"convert", L"Convert to TIFF");
|
|
CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile\\shell\\convert",
|
|
L"command", szConvertCommand);
|
|
return ERROR_SUCCESS; // A very confused return value.
|
|
}
|
|
|
|
// CreateKeyAndValue
|
|
//
|
|
// This routine will create a registry key and assign it a default value.
|
|
//
|
|
// Parameters:
|
|
// hRoot An open registry key.
|
|
// szSubKey A subkey in which the new key will be created. May be NULL.
|
|
// szName Name of the new key. May not be NULL.
|
|
// szDefaultValue Default value for the key. May be NULL.
|
|
//
|
|
// Returns:
|
|
// TRUE on success, FALSE on failure.
|
|
//
|
|
// Author:
|
|
// Brian Dewey (t-briand) 1997-8-7
|
|
static BOOL
|
|
CreateKeyAndValue(HKEY hRoot, LPWSTR szSubKey, LPWSTR szName, LPWSTR szDefaultValue)
|
|
{
|
|
HKEY hSubKey; // Subkey registry key.
|
|
HKEY hKey; // Registry key.
|
|
DWORD dwDisposition; // used in api calls.
|
|
UINT uiStrLen;
|
|
BOOL bCloseSubKey = FALSE; // Do we need to close hSubKey?
|
|
|
|
if(szSubKey != NULL) {
|
|
if(RegOpenKeyExW(
|
|
hRoot,
|
|
szSubKey,
|
|
0,
|
|
KEY_CREATE_SUB_KEY,
|
|
&hSubKey
|
|
) != ERROR_SUCCESS) {
|
|
TRACE((TEXT("CreateKeyAndValue:Unable to open subkey.\r\n")));
|
|
return FALSE;
|
|
} // if(RegOpenKeyExW())
|
|
bCloseSubKey = TRUE;
|
|
} else {
|
|
hSubKey = hRoot; // The subkey is the root...
|
|
}
|
|
|
|
// Now, set up the registry. There are WAY TOO MANY PARAMETERS in this
|
|
// darn API. Some designer needs to chill out!
|
|
if(RegCreateKeyExW(
|
|
hSubKey,
|
|
szName, // We're worried about this extension.
|
|
0, // Reserved.
|
|
NULL, // I have no idea what to put here. Hope this works!
|
|
REG_OPTION_NON_VOLATILE, // This is the default, but I decided to be explicit.
|
|
KEY_ALL_ACCESS, // Be generous with security.
|
|
NULL, // No child process inheritance.
|
|
&hKey, // Store the key here.
|
|
&dwDisposition // The disposition of the call...
|
|
) != ERROR_SUCCESS) {
|
|
TRACE((TEXT("Fax:MigrateSystemNT:Unable to create registry entry.\r\n")));
|
|
} else {
|
|
TRACE((TEXT("Fax:MigrateSystemNT:Created key; disposition = %s.\r\n"),
|
|
(dwDisposition == REG_CREATED_NEW_KEY) ?
|
|
TEXT("REG_CREATED_NEW_KEY") :
|
|
TEXT("REG_OPENED_EXISTING_KEY")));
|
|
}
|
|
|
|
// Only set the value if they passed in a value.
|
|
if(szDefaultValue != NULL) {
|
|
uiStrLen = wcslen(szDefaultValue);
|
|
if(RegSetValueExW(
|
|
hKey,
|
|
NULL, // Trying to set the default value.
|
|
0, // Reserved.
|
|
REG_SZ, // Setting a string value.
|
|
(LPBYTE)szDefaultValue,
|
|
(uiStrLen+1) * sizeof(WCHAR)
|
|
) != ERROR_SUCCESS) {
|
|
TRACE((TEXT("Fax:MigrateSystemNT:Unable to set default value.\r\n")));
|
|
} else {
|
|
TRACE((TEXT("Fax:MigrateSystemNT:Default value set.\r\n")));
|
|
} // if(RegSetValueExW())...
|
|
} // if(szDefaultValue != NULL)...
|
|
RegCloseKey(hKey);
|
|
if(bCloseSubKey) RegCloseKey(hSubKey);
|
|
|
|
return TRUE;
|
|
}
|