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.

338 lines
8.0 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. optdirs.c
  5. Abstract:
  6. Routines for copying optional directories.
  7. Author:
  8. Ted Miller (tedm) 7-Jun-1995
  9. Revision History:
  10. --*/
  11. #include "setupp.h"
  12. #pragma hdrstop
  13. PWSTR OptionalDirSpec;
  14. PWSTR *OptionalDirs;
  15. UINT OptionalDirCount;
  16. BOOL
  17. InitializeOptionalDirList(
  18. VOID
  19. )
  20. /*++
  21. Routine Description:
  22. Initialize the list of optional directories by transforming a
  23. *-delineated list of directories into an array of strings.
  24. Arguments:
  25. None.
  26. Return Value:
  27. Boolean value indicating whether initialization was successful.
  28. If not an entry will have been logged indicating why.
  29. --*/
  30. {
  31. PWSTR p,q;
  32. WCHAR c;
  33. UINT Count,i,Len;
  34. //
  35. // The number of directories is equal to the number of *'s plus one.
  36. //
  37. Len = lstrlen(OptionalDirSpec);
  38. OptionalDirCount = 1;
  39. for(Count=0; Count<Len; Count++) {
  40. if(OptionalDirSpec[Count] == L'*') {
  41. OptionalDirCount++;
  42. }
  43. }
  44. OptionalDirs = MyMalloc(OptionalDirCount * sizeof(PWSTR));
  45. if(!OptionalDirs) {
  46. SetuplogError(
  47. LogSevError,
  48. SETUPLOG_USE_MESSAGEID,
  49. MSG_LOG_OPTIONAL_DIRS,NULL,
  50. SETUPLOG_USE_MESSAGEID,
  51. MSG_LOG_OUTOFMEMORY,
  52. NULL,NULL);
  53. return(FALSE);
  54. }
  55. ZeroMemory(OptionalDirs,OptionalDirCount * sizeof(PWSTR));
  56. p = OptionalDirSpec;
  57. Count = 0;
  58. do {
  59. if((q = wcschr(p,L'*')) == NULL) {
  60. q = wcschr(p,0);
  61. }
  62. c = *q;
  63. *q = 0;
  64. OptionalDirs[Count] = pSetupDuplicateString(p);
  65. *q = c;
  66. if(!OptionalDirs[Count]) {
  67. SetuplogError(
  68. LogSevError,
  69. SETUPLOG_USE_MESSAGEID,
  70. MSG_LOG_OPTIONAL_DIRS,NULL,
  71. SETUPLOG_USE_MESSAGEID,
  72. MSG_LOG_OUTOFMEMORY,
  73. NULL,NULL);
  74. for(i=0; i<Count; i++) {
  75. MyFree(OptionalDirs[i]);
  76. }
  77. MyFree(OptionalDirs);
  78. return(FALSE);
  79. }
  80. Count++;
  81. p = q+1;
  82. } while(c);
  83. return(TRUE);
  84. }
  85. BOOL
  86. QueueFilesInOptionalDirectory(
  87. IN HSPFILEQ FileQ,
  88. IN PCWSTR Directory
  89. )
  90. {
  91. WCHAR FileDirSpec[MAX_PATH];
  92. WIN32_FIND_DATA FindData;
  93. HANDLE FindHandle;
  94. WCHAR c1,c2,c3;
  95. BOOL b;
  96. DWORD Result;
  97. //
  98. // Create the directory in the user's nt tree.
  99. //
  100. Result = GetWindowsDirectory(FileDirSpec,MAX_PATH);
  101. if( Result == 0) {
  102. MYASSERT(FALSE);
  103. return FALSE;
  104. }
  105. pSetupConcatenatePaths(FileDirSpec,Directory,MAX_PATH,NULL);
  106. CreateDirectory(FileDirSpec,NULL);
  107. //
  108. // Form the full name of the directory to iterate
  109. // and add on the search spec.
  110. //
  111. lstrcpyn(FileDirSpec,SourcePath,MAX_PATH);
  112. pSetupConcatenatePaths(FileDirSpec,Directory,MAX_PATH,NULL);
  113. pSetupConcatenatePaths(FileDirSpec,L"*",MAX_PATH,NULL);
  114. b = TRUE;
  115. FindHandle = FindFirstFile(FileDirSpec,&FindData);
  116. if(FindHandle != INVALID_HANDLE_VALUE) {
  117. do {
  118. if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  119. //
  120. // It's a directory. Ignore if current or parent dir spec (. or ..).
  121. //
  122. c1 = FindData.cFileName[0];
  123. c2 = FindData.cFileName[1];
  124. c3 = FindData.cFileName[2];
  125. if(!(((c1 == TEXT('.')) && !c2) || ((c1 == TEXT('.')) && (c2 == TEXT('.')) && !c3))) {
  126. //
  127. // Recurse to handle the child directory.
  128. //
  129. lstrcpyn(FileDirSpec,Directory,MAX_PATH);
  130. pSetupConcatenatePaths(FileDirSpec,FindData.cFileName,MAX_PATH,NULL);
  131. b = QueueFilesInOptionalDirectory(FileQ,FileDirSpec);
  132. }
  133. } else {
  134. //
  135. // It's a file. Queue it up for copy.
  136. //
  137. Result = GetWindowsDirectory(FileDirSpec,MAX_PATH);
  138. if (Result == 0) {
  139. MYASSERT(FALSE);
  140. return FALSE;
  141. }
  142. pSetupConcatenatePaths(FileDirSpec,Directory,MAX_PATH,NULL);
  143. b = SetupQueueCopy(
  144. FileQ,
  145. SourcePath,
  146. Directory,
  147. FindData.cFileName,
  148. NULL,
  149. NULL,
  150. FileDirSpec,
  151. FindData.cFileName,
  152. SP_COPY_DELETESOURCE | BaseCopyStyle
  153. );
  154. if(!b) {
  155. SetuplogError(
  156. LogSevError,
  157. SETUPLOG_USE_MESSAGEID,
  158. MSG_LOG_OPTIONAL_DIR,
  159. Directory, NULL,
  160. SETUPLOG_USE_MESSAGEID,
  161. MSG_LOG_X_RETURNED_WINERR,
  162. L"SetupQueueCopy",
  163. GetLastError(),
  164. NULL,NULL);
  165. }
  166. }
  167. } while(b && FindNextFile(FindHandle,&FindData));
  168. FindClose(FindHandle);
  169. }
  170. return(b);
  171. }
  172. BOOL
  173. CopyOptionalDirectories(
  174. VOID
  175. )
  176. /*++
  177. Routine Description:
  178. Arguments:
  179. None.
  180. Return Value:
  181. Boolean value indicating whether copying was successful.
  182. If not an entry will have been logged indicating why.
  183. --*/
  184. {
  185. UINT u;
  186. BOOL b;
  187. HSPFILEQ FileQ;
  188. PVOID QueueCallbackInfo;
  189. BYTE PrevPolicy;
  190. BOOL ResetPolicy = FALSE;
  191. if(!OptionalDirSpec) {
  192. return(TRUE);
  193. }
  194. //
  195. // Unless the default non-driver signing policy was overridden via an
  196. // answerfile entry, then we want to temporarily turn down the policy level
  197. // to ignore while we copy optional directories. Of course, setupapi log
  198. // entries will still be generated for any unsigned files copied during
  199. // this time, but there'll be no UI.
  200. //
  201. if(!AFNonDrvSignPolicySpecified) {
  202. SetCodeSigningPolicy(PolicyTypeNonDriverSigning, DRIVERSIGN_NONE, &PrevPolicy);
  203. ResetPolicy = TRUE;
  204. }
  205. //
  206. // Initialize the optional directory list.
  207. //
  208. if(!InitializeOptionalDirList()) {
  209. return(FALSE);
  210. }
  211. //
  212. // Initialize a setup file queue.
  213. //
  214. FileQ = SetupOpenFileQueue();
  215. if(FileQ == INVALID_HANDLE_VALUE) {
  216. SetuplogError(
  217. LogSevError,
  218. SETUPLOG_USE_MESSAGEID,
  219. MSG_LOG_OPTIONAL_DIRS,NULL,
  220. SETUPLOG_USE_MESSAGEID,
  221. MSG_LOG_OUTOFMEMORY,
  222. NULL,NULL);
  223. return(FALSE);
  224. }
  225. QueueCallbackInfo = SetupInitDefaultQueueCallbackEx(
  226. MainWindowHandle,
  227. INVALID_HANDLE_VALUE,
  228. 0,0,NULL);
  229. if(!QueueCallbackInfo) {
  230. SetupCloseFileQueue(FileQ);
  231. SetuplogError(
  232. LogSevError,
  233. SETUPLOG_USE_MESSAGEID,
  234. MSG_LOG_OPTIONAL_DIRS,NULL,
  235. SETUPLOG_USE_MESSAGEID,
  236. MSG_LOG_OUTOFMEMORY,
  237. NULL,NULL);
  238. return(FALSE);
  239. }
  240. //
  241. // Queue the files in each directory.
  242. //
  243. b = TRUE;
  244. for(u=0; u<OptionalDirCount; u++) {
  245. if(!QueueFilesInOptionalDirectory(FileQ,OptionalDirs[u])) {
  246. b = FALSE;
  247. }
  248. }
  249. //
  250. // Copy the files in the queue. We do this even if some of the queue
  251. // operations failed, so we get at least a subset of the files copied over.
  252. //
  253. if(!SetupCommitFileQueue(MainWindowHandle,FileQ,SetupDefaultQueueCallback,QueueCallbackInfo)) {
  254. SetuplogError(
  255. LogSevWarning,
  256. SETUPLOG_USE_MESSAGEID,
  257. MSG_LOG_OPTIONAL_DIR_COPY,
  258. NULL,NULL);
  259. b = FALSE;
  260. }
  261. SetupTermDefaultQueueCallback(QueueCallbackInfo);
  262. SetupCloseFileQueue(FileQ);
  263. //
  264. // Now crank the non-driver signing policy back up to what it was prior to
  265. // entering this routine.
  266. //
  267. if(ResetPolicy) {
  268. SetCodeSigningPolicy(PolicyTypeNonDriverSigning, PrevPolicy, NULL);
  269. }
  270. return(b);
  271. }