Source code of Windows XP (NT5)
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.

336 lines
11 KiB

  1. /*++
  2. migrate.c
  3. Copyright (c) 1997 Microsoft Corporation
  4. This module performs Windows 95 to Windows NT fax migration.
  5. Specifically, this file contains the Windows NT side of migration...
  6. Author:
  7. Brian Dewey (t-briand) 1997-7-14
  8. --*/
  9. #include <windows.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <setupapi.h>
  13. #include <wchar.h>
  14. #include <tchar.h>
  15. #include "migrate.h" // Contains prototypes & version information.
  16. #include "debug.h" // Includes TRACE definition
  17. #include "resource.h" // Resources.
  18. // ------------------------------------------------------------
  19. // Global data
  20. // Wide names of the working & source directories.
  21. static WCHAR lpWorkingDir[MAX_PATH],
  22. lpSourceDir[MAX_PATH];
  23. HINSTANCE hinstMigDll;
  24. // ------------------------------------------------------------
  25. // Prototypes
  26. static BOOL CreateKeyAndValue(HKEY hRoot, LPWSTR szSubKey, LPWSTR szName, LPWSTR szDefaultValue);
  27. BOOL WINAPI
  28. DllEntryPoint(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
  29. {
  30. if(dwReason == DLL_PROCESS_ATTACH) {
  31. TRACE((TEXT("Migration DLL attached.\r\n")));
  32. hinstMigDll = hinstDll;
  33. }
  34. return TRUE;
  35. }
  36. // InitializeNT
  37. //
  38. // This routine performs NT-side initialization.
  39. //
  40. // Parameters:
  41. // Documented below.
  42. //
  43. // Returns:
  44. // ERROR_SUCCESS.
  45. //
  46. // Author:
  47. // Brian Dewey (t-briand) 1997-7-14
  48. LONG
  49. CALLBACK
  50. InitializeNT(
  51. IN LPCWSTR WorkingDirectory, // Working directory for temporary files.
  52. IN LPCWSTR SourceDirectory, // Directory of winNT source.
  53. LPVOID Reserved // It's reserved.
  54. )
  55. {
  56. TRACE((TEXT("Fax Migration:NT Side Initialized.\r\n")));
  57. wcscpy(lpWorkingDir, WorkingDirectory);
  58. wcscpy(lpSourceDir, SourceDirectory);
  59. return ERROR_SUCCESS; // A very confused return value.
  60. }
  61. // MigrateUserNT
  62. //
  63. // Sets up user information.
  64. //
  65. // Parameters:
  66. // Documented below.
  67. //
  68. // Returns:
  69. // ERROR_SUCCESS.
  70. //
  71. // Author:
  72. // Brian Dewey (t-briand) 1997-7-14
  73. LONG
  74. CALLBACK
  75. MigrateUserNT(
  76. IN HINF UnattendInfHandle, // Access to the unattend.txt file.
  77. IN HKEY UserRegHandle, // Handle to registry settings for user.
  78. IN LPCWSTR UserName, // Name of the user.
  79. LPVOID Reserved
  80. )
  81. {
  82. // our task: copy entries from szInfFileName to the registry.
  83. LPTSTR lpNTOptions = TEXT("Software\\Microsoft\\Fax\\UserInfo");
  84. HKEY hReg; // Registry key for user.
  85. LPCTSTR alpKeys[] = { // This array defines what keys will be
  86. TEXT("Address"), // copied from faxuser.ini into the registry.
  87. TEXT("Company"),
  88. TEXT("Department"),
  89. TEXT("FaxNumber"),
  90. TEXT("FullName"),
  91. TEXT("HomePhone"),
  92. TEXT("Mailbox"),
  93. TEXT("Office"),
  94. TEXT("OfficePhone"),
  95. TEXT("Title")
  96. };
  97. UINT iCount, iMax; // used for looping through all the sections.
  98. UINT i; // Used for converting doubled ';' to CR/LF pairs.
  99. TCHAR szValue[MAX_PATH];
  100. TCHAR szInfFileNameRes[MAX_PATH];
  101. TCHAR szUser[MAX_PATH]; // TCHAR representation of the user name.
  102. LONG lError; // Holds a returned error code.
  103. if(UserName == NULL) {
  104. // NULL means the logon user.
  105. _tcscpy(szUser, lpLogonUser);// Get the logon user name for faxuser.ini
  106. } else {
  107. #ifdef _UNICODE
  108. // If this is a unicode compile, UserName and szUser are the same. Just
  109. // copy one to the other.
  110. wcscpy(szUser, UserName);
  111. #else
  112. // We need to convert the wide UserName to the narrow szUser.
  113. WideCharToMultiByte(
  114. CP_ACP, // Convert to ANSI.
  115. 0, // No flags.
  116. UserName, // The wide char set.
  117. -1, // Null-terminated string.
  118. szUser, // Holds the converted string.
  119. sizeof(szUser), // Size of this buffer...
  120. NULL, // Use default unmappable character.
  121. NULL // I don't need to know if I used the default.
  122. );
  123. #endif // _UNICODE
  124. }
  125. TRACE((TEXT("(MigrateUserNT):Migrating user '%s'.\r\n"), szUser));
  126. if(RegOpenKeyEx(UserRegHandle,
  127. lpNTOptions, // Open this subkey.
  128. 0, // Reserved.
  129. KEY_WRITE, // We want write permission.
  130. &hReg) != ERROR_SUCCESS) {
  131. // All I'm allowed to do is return obscure error codes...
  132. // However, unless there's a hardware failure, I'm supposed to say
  133. // everything's OK.
  134. return ERROR_SUCCESS;
  135. }
  136. iMax = sizeof(alpKeys) / sizeof(LPCTSTR);
  137. _stprintf(szInfFileNameRes, TEXT("%s\\migrate.inf"), lpWorkingDir);
  138. ExpandEnvironmentStrings(szInfFileNameRes, szInfFileName, MAX_PATH);
  139. TRACE((TEXT("Reading from file %s.\r\n"), szInfFileName));
  140. for(iCount = 0; iCount < iMax; iCount++) {
  141. GetPrivateProfileString(
  142. szUser,
  143. alpKeys[iCount],
  144. TEXT(""),
  145. szValue,
  146. sizeof(szValue),
  147. szInfFileName
  148. );
  149. // If there was a CR/LF pair, the w95 side of things converted it
  150. // to a doubled semicolon. So I'm going to look for doubled semicolons
  151. // and convert them to CR/LF pairs.
  152. i = 0;
  153. while(szValue[i] != _T('\0')) {
  154. if((szValue[i] == _T(';')) && (szValue[i+1] == _T(';'))) {
  155. // Found a doubled semicolon.
  156. szValue[i] = '\r';
  157. szValue[i+1] = '\n';
  158. TRACE((TEXT("Doing newline translation.\r\n")));
  159. }
  160. i++;
  161. }
  162. lError = RegSetValueEx(hReg,
  163. alpKeys[iCount],
  164. 0,
  165. REG_SZ,
  166. szValue,
  167. _tcslen(szValue)+1);
  168. if(lError != ERROR_SUCCESS) {
  169. TRACE((TEXT("Error in RegSetValueEx():%x\r\n"), lError));
  170. return lError;
  171. }
  172. TRACE((TEXT("%s = %s\r\n"), alpKeys[iCount], szValue));
  173. }
  174. RegCloseKey(hReg);
  175. return ERROR_SUCCESS; // A very confused return value.
  176. }
  177. // MigrateSystemNT
  178. //
  179. // Updates the system registry to associate 'awdvstub.exe' with the
  180. // AWD extension.
  181. //
  182. // Parameters:
  183. // Documented below.
  184. //
  185. // Returns:
  186. // ERROR_SUCCESS.
  187. //
  188. // Author:
  189. // Brian Dewey (t-briand) 1997-7-14
  190. LONG
  191. CALLBACK
  192. MigrateSystemNT(
  193. IN HINF UnattendInfHandle, // Access to the unattend.txt file.
  194. LPVOID Reserved
  195. )
  196. {
  197. WCHAR szExeFileName[MAX_PATH];
  198. WCHAR szWindowsDir[MAX_PATH];
  199. WCHAR szDestFile[MAX_PATH];
  200. WCHAR szOpenCommand[MAX_PATH + 16];
  201. WCHAR szConvertCommand[MAX_PATH + 16]; // "*" /c "%1"
  202. // first, copy 'awdvstub.exe' to %SystemRoot%\system32.
  203. GetWindowsDirectoryW(szWindowsDir, MAX_PATH);
  204. swprintf(szExeFileName, L"%s\\%s", lpWorkingDir, L"awdvstub.exe");
  205. swprintf(szDestFile, L"%s\\system32\\%s", szWindowsDir, L"awdvstub.exe");
  206. if(!CopyFileW(szExeFileName,
  207. szDestFile,
  208. FALSE)) {
  209. TRACE((TEXT("Fax:MigrateSystemNT:Copy file failed.\r\n")));
  210. } else {
  211. TRACE((TEXT("Fax:MigrateSystemNT:Copy file succeeded.\r\n")));
  212. }
  213. // Generate the command lines.
  214. swprintf(szOpenCommand, L"\"%s\" \"%%1\"", szDestFile);
  215. swprintf(szConvertCommand, L"\"%s\" /c \"%%1\"", szDestFile);
  216. // Now, update the registry.
  217. CreateKeyAndValue(HKEY_CLASSES_ROOT, NULL, L".awd", L"awdfile");
  218. CreateKeyAndValue(HKEY_CLASSES_ROOT, NULL, L"awdfile", L"Windows 95 Fax File (obsolete)");
  219. CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile", L"shell", NULL);
  220. CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile\\shell", L"open", NULL);
  221. CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile\\shell\\open", L"command", szOpenCommand);
  222. CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile\\shell", L"convert", L"Convert to TIFF");
  223. CreateKeyAndValue(HKEY_CLASSES_ROOT, L"awdfile\\shell\\convert",
  224. L"command", szConvertCommand);
  225. return ERROR_SUCCESS; // A very confused return value.
  226. }
  227. // CreateKeyAndValue
  228. //
  229. // This routine will create a registry key and assign it a default value.
  230. //
  231. // Parameters:
  232. // hRoot An open registry key.
  233. // szSubKey A subkey in which the new key will be created. May be NULL.
  234. // szName Name of the new key. May not be NULL.
  235. // szDefaultValue Default value for the key. May be NULL.
  236. //
  237. // Returns:
  238. // TRUE on success, FALSE on failure.
  239. //
  240. // Author:
  241. // Brian Dewey (t-briand) 1997-8-7
  242. static BOOL
  243. CreateKeyAndValue(HKEY hRoot, LPWSTR szSubKey, LPWSTR szName, LPWSTR szDefaultValue)
  244. {
  245. HKEY hSubKey; // Subkey registry key.
  246. HKEY hKey; // Registry key.
  247. DWORD dwDisposition; // used in api calls.
  248. UINT uiStrLen;
  249. BOOL bCloseSubKey = FALSE; // Do we need to close hSubKey?
  250. if(szSubKey != NULL) {
  251. if(RegOpenKeyExW(
  252. hRoot,
  253. szSubKey,
  254. 0,
  255. KEY_CREATE_SUB_KEY,
  256. &hSubKey
  257. ) != ERROR_SUCCESS) {
  258. TRACE((TEXT("CreateKeyAndValue:Unable to open subkey.\r\n")));
  259. return FALSE;
  260. } // if(RegOpenKeyExW())
  261. bCloseSubKey = TRUE;
  262. } else {
  263. hSubKey = hRoot; // The subkey is the root...
  264. }
  265. // Now, set up the registry. There are WAY TOO MANY PARAMETERS in this
  266. // darn API. Some designer needs to chill out!
  267. if(RegCreateKeyExW(
  268. hSubKey,
  269. szName, // We're worried about this extension.
  270. 0, // Reserved.
  271. NULL, // I have no idea what to put here. Hope this works!
  272. REG_OPTION_NON_VOLATILE, // This is the default, but I decided to be explicit.
  273. KEY_ALL_ACCESS, // Be generous with security.
  274. NULL, // No child process inheritance.
  275. &hKey, // Store the key here.
  276. &dwDisposition // The disposition of the call...
  277. ) != ERROR_SUCCESS) {
  278. TRACE((TEXT("Fax:MigrateSystemNT:Unable to create registry entry.\r\n")));
  279. } else {
  280. TRACE((TEXT("Fax:MigrateSystemNT:Created key; disposition = %s.\r\n"),
  281. (dwDisposition == REG_CREATED_NEW_KEY) ?
  282. TEXT("REG_CREATED_NEW_KEY") :
  283. TEXT("REG_OPENED_EXISTING_KEY")));
  284. }
  285. // Only set the value if they passed in a value.
  286. if(szDefaultValue != NULL) {
  287. uiStrLen = wcslen(szDefaultValue);
  288. if(RegSetValueExW(
  289. hKey,
  290. NULL, // Trying to set the default value.
  291. 0, // Reserved.
  292. REG_SZ, // Setting a string value.
  293. (LPBYTE)szDefaultValue,
  294. (uiStrLen+1) * sizeof(WCHAR)
  295. ) != ERROR_SUCCESS) {
  296. TRACE((TEXT("Fax:MigrateSystemNT:Unable to set default value.\r\n")));
  297. } else {
  298. TRACE((TEXT("Fax:MigrateSystemNT:Default value set.\r\n")));
  299. } // if(RegSetValueExW())...
  300. } // if(szDefaultValue != NULL)...
  301. RegCloseKey(hKey);
  302. if(bCloseSubKey) RegCloseKey(hSubKey);
  303. return TRUE;
  304. }