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.

364 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. instutil.c
  5. Abstract:
  6. Common code for INSTALER.EXE, DISPINST.EXE, COMPINST.EXE and UNDOINST.EXE
  7. Author:
  8. Steve Wood (stevewo) 14-Jan-1996
  9. Revision History:
  10. --*/
  11. #include "instutil.h"
  12. #include "iml.h"
  13. LPSTR SavedModuleName;
  14. LPSTR SavedModuleUsage1;
  15. LPSTR SavedModuleUsage2;
  16. WCHAR AltTempFilePathBuffer[ MAX_PATH ];
  17. PWSTR AltTempFilePathFileName;
  18. WCHAR TempFilePathBuffer[ MAX_PATH ];
  19. PWSTR TempFilePathFileName;
  20. USHORT TempFileNextUniqueId;
  21. BOOL WINAPI
  22. CtrlCHandler(
  23. ULONG CtrlType
  24. )
  25. {
  26. //
  27. // Ignore control C interrupts. Let child process deal with them
  28. // if it wants. If it doesn't then it will terminate and we will
  29. // get control and terminate ourselves
  30. //
  31. return TRUE;
  32. }
  33. void
  34. InitCommonCode(
  35. LPSTR ModuleName,
  36. LPSTR ModuleUsage1,
  37. LPSTR ModuleUsage2
  38. )
  39. {
  40. SavedModuleName = ModuleName;
  41. SavedModuleUsage1 = ModuleUsage1;
  42. SavedModuleUsage2 = ModuleUsage2;
  43. GetTempPath( sizeof( TempFilePathBuffer ) / sizeof( WCHAR ),
  44. TempFilePathBuffer
  45. );
  46. TempFilePathFileName = TempFilePathBuffer + wcslen( TempFilePathBuffer );
  47. TempFileNextUniqueId = (USHORT)0x0001;
  48. InstalerDirectory[ 0 ] = UNICODE_NULL;
  49. return;
  50. }
  51. void
  52. DisplayIndentedString(
  53. ULONG IndentAmount,
  54. PCHAR sBegin
  55. )
  56. {
  57. PCHAR sEnd;
  58. while (sBegin != NULL) {
  59. sEnd = sBegin;
  60. while (*sEnd && *sEnd != '\n') {
  61. sEnd += 1;
  62. }
  63. fprintf( stderr, "%.*s%.*s\n",
  64. IndentAmount,
  65. " ",
  66. sEnd - sBegin, sBegin
  67. );
  68. if (*sEnd == '\0') {
  69. break;
  70. }
  71. else {
  72. sBegin = ++sEnd;
  73. }
  74. }
  75. return;
  76. }
  77. void
  78. Usage(
  79. LPSTR Message,
  80. ULONG MessageParameter
  81. )
  82. {
  83. ULONG n;
  84. LPSTR sBegin, sEnd;
  85. n = fprintf( stderr, "usage: %s ", SavedModuleName );
  86. fprintf( stderr, "InstallationName\n" );
  87. DisplayIndentedString( n, SavedModuleUsage1 );
  88. fprintf( stderr, "\n" );
  89. n = fprintf( stderr, "where: " );
  90. fprintf( stderr, "InstallationName specifies a name for the installation. This is a required parameter.\n" );
  91. DisplayIndentedString( n,
  92. "-? Displays this message."
  93. );
  94. fprintf( stderr, "\n" );
  95. DisplayIndentedString( n, SavedModuleUsage2 );
  96. if (Message != NULL) {
  97. fprintf( stderr, "\n" );
  98. }
  99. //
  100. // No return from FatalError
  101. //
  102. FatalError( Message, MessageParameter, 0 );
  103. }
  104. void
  105. FatalError(
  106. LPSTR Message,
  107. ULONG MessageParameter1,
  108. ULONG MessageParameter2
  109. )
  110. {
  111. if (Message != NULL) {
  112. fprintf( stderr, "%s: ", SavedModuleName );
  113. fprintf( stderr, Message, MessageParameter1, MessageParameter2 );
  114. fprintf( stderr, "\n" );
  115. }
  116. exit( 1 );
  117. }
  118. PWSTR
  119. GetArgAsUnicode(
  120. LPSTR s
  121. )
  122. {
  123. ULONG n;
  124. PWSTR ps;
  125. n = strlen( s );
  126. ps = HeapAlloc( GetProcessHeap(),
  127. 0,
  128. (n + 1) * sizeof( WCHAR )
  129. );
  130. if (ps == NULL) {
  131. FatalError( "Out of memory", 0, 0 );
  132. }
  133. if (MultiByteToWideChar( CP_ACP,
  134. MB_PRECOMPOSED,
  135. s,
  136. n,
  137. ps,
  138. n
  139. ) != (LONG)n
  140. ) {
  141. FatalError( "Unable to convert parameter '%s' to Unicode (%u)", (ULONG)s, GetLastError() );
  142. }
  143. ps[ n ] = UNICODE_NULL;
  144. return ps;
  145. }
  146. void
  147. CommonSwitchProcessing(
  148. PULONG argc,
  149. PCHAR **argv,
  150. CHAR c
  151. )
  152. {
  153. DWORD dwFileAttributes;
  154. PWSTR s;
  155. switch( c = (CHAR)tolower( c ) ) {
  156. case 'd':
  157. DebugOutput = TRUE;
  158. break;
  159. case '?':
  160. Usage( NULL, 0 );
  161. break;
  162. default:
  163. Usage( "Invalid switch (-%c)", (ULONG)c );
  164. break;
  165. }
  166. return;
  167. }
  168. BOOLEAN
  169. CommonArgProcessing(
  170. PULONG argc,
  171. PCHAR **argv
  172. )
  173. {
  174. PWSTR s;
  175. if (InstallationName == NULL) {
  176. if (GetCurrentDirectory( MAX_PATH, InstalerDirectory ) != 0) {
  177. s = wcschr( InstalerDirectory, UNICODE_NULL );
  178. if (s && s > InstalerDirectory && s[-1] != L'\\') {
  179. *s++ = L'\\';
  180. *s = UNICODE_NULL;
  181. }
  182. InstallationName = GetArgAsUnicode( **argv );
  183. ImlPath = FormatImlPath( InstalerDirectory, InstallationName );
  184. return TRUE;
  185. }
  186. }
  187. return FALSE;
  188. }
  189. PWSTR
  190. FormatTempFileName(
  191. PWSTR Directory,
  192. PUSHORT TempFileUniqueId
  193. )
  194. {
  195. if (*TempFileUniqueId == 0) {
  196. *TempFileUniqueId = (USHORT)(TempFileNextUniqueId++);
  197. if (TempFileNextUniqueId == 0) {
  198. return NULL;
  199. }
  200. }
  201. else
  202. if (*TempFileUniqueId == 0xFFFF) {
  203. return NULL;
  204. }
  205. if (Directory != NULL) {
  206. GetFullPathName( Directory, MAX_PATH, AltTempFilePathBuffer, &AltTempFilePathFileName );
  207. AltTempFilePathFileName = wcsrchr( AltTempFilePathBuffer, TEXT('\\') );
  208. AltTempFilePathFileName += 1;
  209. swprintf( AltTempFilePathFileName, L"~INS%04x.TMP", *TempFileUniqueId );
  210. return AltTempFilePathBuffer;
  211. }
  212. else {
  213. swprintf( TempFilePathFileName, L"~INS%04x.TMP", *TempFileUniqueId );
  214. return TempFilePathBuffer;
  215. }
  216. }
  217. PWSTR
  218. CreateBackupFileName(
  219. PUSHORT TempFileUniqueId
  220. )
  221. {
  222. PWSTR BackupFileName;
  223. while (BackupFileName = FormatTempFileName( NULL, TempFileUniqueId )) {
  224. if (GetFileAttributesW( BackupFileName ) == 0xFFFFFFFF) {
  225. break;
  226. }
  227. else {
  228. *TempFileUniqueId = 0; // Temp file name existed, try next unique id
  229. }
  230. }
  231. return BackupFileName;
  232. }
  233. UCHAR EnumTypeBuffer0[ 512 ];
  234. UCHAR EnumTypeBuffer1[ 512 ];
  235. UCHAR EnumTypeBuffer2[ 512 ];
  236. UCHAR EnumTypeBuffer3[ 512 ];
  237. LPSTR EnumTypeBuffers[ 4 ] = {
  238. EnumTypeBuffer0,
  239. EnumTypeBuffer1,
  240. EnumTypeBuffer2,
  241. EnumTypeBuffer3
  242. };
  243. LPSTR
  244. FormatEnumType(
  245. ULONG BufferIndex,
  246. PENUM_TYPE_NAMES Table,
  247. ULONG Value,
  248. BOOLEAN FlagFormat
  249. )
  250. {
  251. LPSTR s, FlagsBuffer = EnumTypeBuffers[ BufferIndex ];
  252. FlagsBuffer[ 0 ] = '\0';
  253. while (Table->Value != 0xFFFFFFFF) {
  254. if (FlagFormat) {
  255. if (Table->Value & Value) {
  256. if (FlagsBuffer[ 0 ] != '\0') {
  257. strcat( FlagsBuffer, " | " );
  258. }
  259. strcat( FlagsBuffer, Table->Name );
  260. Value &= ~Table->Value;
  261. if (Value == 0) {
  262. return FlagsBuffer;
  263. }
  264. }
  265. }
  266. else
  267. if (Table->Value == Value) {
  268. if (Value == 0) {
  269. if (!strcmp( Table->Name, "STATUS_WAIT_0" )) {
  270. return "STATUS_SUCCESS";
  271. }
  272. else
  273. if (!strcmp( Table->Name, "ERROR_SUCCESS" )) {
  274. return "NO_ERROR";
  275. }
  276. }
  277. return Table->Name;
  278. }
  279. Table += 1;
  280. }
  281. s = FlagsBuffer;
  282. if (FlagFormat) {
  283. if (s[ 0 ] != '\0') {
  284. strcat( s, " | " );
  285. s += strlen( s );
  286. }
  287. }
  288. sprintf( s, Table->Name ? Table->Name : "%x", Value );
  289. return FlagsBuffer;
  290. }
  291. ENUM_TYPE_NAMES ValueDataTypeNames[] = {
  292. REG_NONE, "REG_NONE",
  293. REG_SZ, "REG_SZ",
  294. REG_EXPAND_SZ, "REG_EXPAND_SZ",
  295. REG_BINARY, "REG_BINARY",
  296. REG_DWORD, "REG_DWORD",
  297. REG_DWORD_BIG_ENDIAN, "REG_DWORD_BIG_ENDIAN",
  298. REG_LINK, "REG_LINK",
  299. REG_MULTI_SZ, "REG_MULTI_SZ",
  300. REG_RESOURCE_LIST, "REG_RESOURCE_LIST",
  301. REG_FULL_RESOURCE_DESCRIPTOR, "REG_FULL_RESOURCE_DESCRIPTOR",
  302. REG_RESOURCE_REQUIREMENTS_LIST,"REG_RESOURCE_REQUIREMENTS_LIST",
  303. 0xFFFFFFFF, "%x"
  304. };