Leaked source code of windows server 2003
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.

410 lines
10 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. ULONG remainingLen;
  196. if (*TempFileUniqueId == 0) {
  197. *TempFileUniqueId = (USHORT)(TempFileNextUniqueId++);
  198. if (TempFileNextUniqueId == 0) {
  199. return NULL;
  200. }
  201. }
  202. else
  203. if (*TempFileUniqueId == 0xFFFF) {
  204. return NULL;
  205. }
  206. if (Directory != NULL) {
  207. GetFullPathName( Directory, MAX_PATH, AltTempFilePathBuffer, &AltTempFilePathFileName );
  208. AltTempFilePathFileName = wcsrchr( AltTempFilePathBuffer, TEXT('\\') );
  209. if (NULL == AltTempFilePathFileName) {
  210. return NULL;
  211. }
  212. AltTempFilePathFileName += 1;
  213. //
  214. // Calculate how much space we have left
  215. //
  216. remainingLen = MAX_PATH - 1 - (AltTempFilePathFileName - AltTempFilePathBuffer);
  217. _snwprintf( AltTempFilePathFileName,
  218. remainingLen,
  219. L"~INS%04x.TMP", *TempFileUniqueId );
  220. return AltTempFilePathBuffer;
  221. }
  222. else {
  223. if (TempFilePathFileName < TempFilePathBuffer ||
  224. TempFilePathFileName >= TempFilePathBuffer + MAX_PATH) {
  225. return NULL;
  226. }
  227. remainingLen = MAX_PATH - 1 - (TempFilePathFileName - TempFilePathBuffer);
  228. _snwprintf( TempFilePathFileName,
  229. remainingLen,
  230. L"~INS%04x.TMP", *TempFileUniqueId );
  231. return TempFilePathBuffer;
  232. }
  233. }
  234. PWSTR
  235. CreateBackupFileName(
  236. PUSHORT TempFileUniqueId
  237. )
  238. {
  239. PWSTR BackupFileName;
  240. while (BackupFileName = FormatTempFileName( NULL, TempFileUniqueId )) {
  241. if (GetFileAttributesW( BackupFileName ) == 0xFFFFFFFF) {
  242. break;
  243. }
  244. else {
  245. *TempFileUniqueId = 0; // Temp file name existed, try next unique id
  246. }
  247. }
  248. return BackupFileName;
  249. }
  250. UCHAR EnumTypeBuffer0[ 512 ];
  251. UCHAR EnumTypeBuffer1[ 512 ];
  252. UCHAR EnumTypeBuffer2[ 512 ];
  253. UCHAR EnumTypeBuffer3[ 512 ];
  254. LPSTR EnumTypeBuffers[ 4 ] = {
  255. EnumTypeBuffer0,
  256. EnumTypeBuffer1,
  257. EnumTypeBuffer2,
  258. EnumTypeBuffer3
  259. };
  260. LPSTR
  261. FormatEnumType(
  262. ULONG BufferIndex,
  263. PENUM_TYPE_NAMES Table,
  264. ULONG Value,
  265. BOOLEAN FlagFormat
  266. )
  267. {
  268. LPSTR s, FlagsBuffer = EnumTypeBuffers[ BufferIndex ];
  269. ULONG remainingLen;
  270. //
  271. // 02/19/2002 - BogdanA - make some calculations so
  272. // we do not overflow the static buffers...
  273. //
  274. remainingLen = sizeof(FlagsBuffer)/sizeof(FlagsBuffer[0]) - 1;
  275. FlagsBuffer[ 0 ] = '\0';
  276. FlagsBuffer[remainingLen] = 0;
  277. while (Table->Value != 0xFFFFFFFF) {
  278. if (FlagFormat) {
  279. if (Table->Value & Value) {
  280. if (FlagsBuffer[ 0 ] != '\0') {
  281. //
  282. // Check that we can still add stuff...
  283. //
  284. if (remainingLen < strlen(" | ")) {
  285. return FlagsBuffer;
  286. }
  287. remainingLen -= strlen(" | ");
  288. strcat( FlagsBuffer, " | " );
  289. }
  290. if (remainingLen < strlen(Table->Name)) {
  291. return FlagsBuffer;
  292. }
  293. remainingLen -= strlen(Table->Name);
  294. strcat( FlagsBuffer, Table->Name );
  295. Value &= ~Table->Value;
  296. if (Value == 0) {
  297. return FlagsBuffer;
  298. }
  299. }
  300. }
  301. else
  302. if (Table->Value == Value) {
  303. if (Value == 0) {
  304. if (!strcmp( Table->Name, "STATUS_WAIT_0" )) {
  305. return "STATUS_SUCCESS";
  306. }
  307. else
  308. if (!strcmp( Table->Name, "ERROR_SUCCESS" )) {
  309. return "NO_ERROR";
  310. }
  311. }
  312. return Table->Name;
  313. }
  314. Table += 1;
  315. }
  316. s = FlagsBuffer;
  317. //
  318. // remainingLen should be computed above, use it here again
  319. //
  320. if (FlagFormat) {
  321. if (s[ 0 ] != '\0') {
  322. if (remainingLen < strlen(" | ")) {
  323. return FlagsBuffer;
  324. }
  325. remainingLen -= strlen(" | ");
  326. strcat( s, " | " );
  327. s += strlen( s );
  328. }
  329. }
  330. _snprintf( s, remainingLen, Table->Name ? Table->Name : "%x", Value );
  331. return FlagsBuffer;
  332. }
  333. ENUM_TYPE_NAMES ValueDataTypeNames[] = {
  334. REG_NONE, "REG_NONE",
  335. REG_SZ, "REG_SZ",
  336. REG_EXPAND_SZ, "REG_EXPAND_SZ",
  337. REG_BINARY, "REG_BINARY",
  338. REG_DWORD, "REG_DWORD",
  339. REG_DWORD_BIG_ENDIAN, "REG_DWORD_BIG_ENDIAN",
  340. REG_LINK, "REG_LINK",
  341. REG_MULTI_SZ, "REG_MULTI_SZ",
  342. REG_RESOURCE_LIST, "REG_RESOURCE_LIST",
  343. REG_FULL_RESOURCE_DESCRIPTOR, "REG_FULL_RESOURCE_DESCRIPTOR",
  344. REG_RESOURCE_REQUIREMENTS_LIST,"REG_RESOURCE_REQUIREMENTS_LIST",
  345. 0xFFFFFFFF, "%x"
  346. };