Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenqueue.c
Go to the documentation of this file.
00001 /* 00002 * Setupapi file queue routines 00003 * 00004 * Copyright 2002 Alexandre Julliard for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "setupapi_private.h" 00022 00023 WINE_DEFAULT_DEBUG_CHANNEL(setupapi); 00024 00025 /* Unicode constants */ 00026 static const WCHAR DotSecurity[] = {'.','S','e','c','u','r','i','t','y',0}; 00027 00028 /* context structure for the default queue callback */ 00029 struct default_callback_context 00030 { 00031 HWND owner; 00032 HWND progress; 00033 UINT message; 00034 }; 00035 00036 struct file_op 00037 { 00038 struct file_op *next; 00039 UINT style; 00040 WCHAR *src_root; 00041 WCHAR *src_path; 00042 WCHAR *src_file; 00043 WCHAR *src_descr; 00044 WCHAR *src_tag; 00045 WCHAR *dst_path; 00046 WCHAR *dst_file; 00047 PSECURITY_DESCRIPTOR dst_sd; 00048 }; 00049 00050 struct file_op_queue 00051 { 00052 struct file_op *head; 00053 struct file_op *tail; 00054 unsigned int count; 00055 }; 00056 00057 struct file_queue 00058 { 00059 struct file_op_queue copy_queue; 00060 struct file_op_queue delete_queue; 00061 struct file_op_queue rename_queue; 00062 DWORD flags; 00063 }; 00064 00065 00066 static inline WCHAR *strdupW( const WCHAR *str ) 00067 { 00068 WCHAR *ret = NULL; 00069 if (str) 00070 { 00071 int len = (strlenW(str) + 1) * sizeof(WCHAR); 00072 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( ret, str, len ); 00073 } 00074 return ret; 00075 } 00076 00077 static inline char *strdupWtoA( const WCHAR *str ) 00078 { 00079 char *ret = NULL; 00080 if (str) 00081 { 00082 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); 00083 if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) 00084 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); 00085 } 00086 return ret; 00087 } 00088 00089 /* append a file operation to a queue */ 00090 static inline void queue_file_op( struct file_op_queue *queue, struct file_op *op ) 00091 { 00092 op->next = NULL; 00093 if (queue->tail) queue->tail->next = op; 00094 else queue->head = op; 00095 queue->tail = op; 00096 queue->count++; 00097 } 00098 00099 /* free all the file operations on a given queue */ 00100 static void free_file_op_queue( struct file_op_queue *queue ) 00101 { 00102 struct file_op *t, *op = queue->head; 00103 00104 while( op ) 00105 { 00106 HeapFree( GetProcessHeap(), 0, op->src_root ); 00107 HeapFree( GetProcessHeap(), 0, op->src_path ); 00108 HeapFree( GetProcessHeap(), 0, op->src_file ); 00109 HeapFree( GetProcessHeap(), 0, op->src_descr ); 00110 HeapFree( GetProcessHeap(), 0, op->src_tag ); 00111 HeapFree( GetProcessHeap(), 0, op->dst_path ); 00112 if (op->dst_sd) LocalFree( op->dst_sd); 00113 if (op->dst_file != op->src_file) HeapFree( GetProcessHeap(), 0, op->dst_file ); 00114 t = op; 00115 op = op->next; 00116 HeapFree( GetProcessHeap(), 0, t ); 00117 } 00118 } 00119 00120 /* concat 3 strings to make a path, handling separators correctly */ 00121 static void concat_W( WCHAR *buffer, const WCHAR *src1, const WCHAR *src2, const WCHAR *src3 ) 00122 { 00123 *buffer = 0; 00124 if (src1 && *src1) 00125 { 00126 strcpyW( buffer, src1 ); 00127 buffer += strlenW(buffer ); 00128 if (buffer[-1] != '\\') *buffer++ = '\\'; 00129 if (src2) while (*src2 == '\\') src2++; 00130 } 00131 00132 if (src2) 00133 { 00134 strcpyW( buffer, src2 ); 00135 buffer += strlenW(buffer ); 00136 if (buffer[-1] != '\\') *buffer++ = '\\'; 00137 if (src3) while (*src3 == '\\') src3++; 00138 } 00139 if (src3) 00140 { 00141 strcpyW( buffer, src3 ); 00142 buffer += strlenW(buffer ); 00143 } 00144 } 00145 00146 00147 /*********************************************************************** 00148 * build_filepathsW 00149 * 00150 * Build a FILEPATHS_W structure for a given file operation. 00151 */ 00152 static BOOL build_filepathsW( const struct file_op *op, FILEPATHS_W *paths ) 00153 { 00154 unsigned int src_len = 1, dst_len = 1; 00155 WCHAR *source = (PWSTR)paths->Source, *target = (PWSTR)paths->Target; 00156 00157 if (op->src_root) src_len += strlenW(op->src_root) + 1; 00158 if (op->src_path) src_len += strlenW(op->src_path) + 1; 00159 if (op->src_file) src_len += strlenW(op->src_file) + 1; 00160 if (op->dst_path) dst_len += strlenW(op->dst_path) + 1; 00161 if (op->dst_file) dst_len += strlenW(op->dst_file) + 1; 00162 src_len *= sizeof(WCHAR); 00163 dst_len *= sizeof(WCHAR); 00164 00165 if (!source || HeapSize( GetProcessHeap(), 0, source ) < src_len ) 00166 { 00167 HeapFree( GetProcessHeap(), 0, source ); 00168 paths->Source = source = HeapAlloc( GetProcessHeap(), 0, src_len ); 00169 } 00170 if (!target || HeapSize( GetProcessHeap(), 0, target ) < dst_len ) 00171 { 00172 HeapFree( GetProcessHeap(), 0, target ); 00173 paths->Target = target = HeapAlloc( GetProcessHeap(), 0, dst_len ); 00174 } 00175 if (!source || !target) return FALSE; 00176 concat_W( source, op->src_root, op->src_path, op->src_file ); 00177 concat_W( target, NULL, op->dst_path, op->dst_file ); 00178 paths->Win32Error = 0; 00179 paths->Flags = 0; 00180 return TRUE; 00181 } 00182 00183 00184 /*********************************************************************** 00185 * QUEUE_callback_WtoA 00186 * 00187 * Map a file callback parameters from W to A and call the A callback. 00188 */ 00189 UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, 00190 UINT_PTR param1, UINT_PTR param2 ) 00191 { 00192 struct callback_WtoA_context *callback_ctx = context; 00193 char buffer[MAX_PATH]; 00194 UINT ret; 00195 UINT_PTR old_param2 = param2; 00196 00197 switch(notification) 00198 { 00199 case SPFILENOTIFY_COPYERROR: 00200 param2 = (UINT_PTR)&buffer; 00201 /* fall through */ 00202 case SPFILENOTIFY_STARTDELETE: 00203 case SPFILENOTIFY_ENDDELETE: 00204 case SPFILENOTIFY_DELETEERROR: 00205 case SPFILENOTIFY_STARTRENAME: 00206 case SPFILENOTIFY_ENDRENAME: 00207 case SPFILENOTIFY_RENAMEERROR: 00208 case SPFILENOTIFY_STARTCOPY: 00209 case SPFILENOTIFY_ENDCOPY: 00210 case SPFILENOTIFY_QUEUESCAN_EX: 00211 { 00212 FILEPATHS_W *pathsW = (FILEPATHS_W *)param1; 00213 FILEPATHS_A pathsA; 00214 00215 pathsA.Source = strdupWtoA( pathsW->Source ); 00216 pathsA.Target = strdupWtoA( pathsW->Target ); 00217 pathsA.Win32Error = pathsW->Win32Error; 00218 pathsA.Flags = pathsW->Flags; 00219 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, 00220 (UINT_PTR)&pathsA, param2 ); 00221 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Source ); 00222 HeapFree( GetProcessHeap(), 0, (void *)pathsA.Target ); 00223 } 00224 if (notification == SPFILENOTIFY_COPYERROR) 00225 MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH ); 00226 break; 00227 00228 case SPFILENOTIFY_STARTREGISTRATION: 00229 case SPFILENOTIFY_ENDREGISTRATION: 00230 { 00231 SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1; 00232 SP_REGISTER_CONTROL_STATUSA statusA; 00233 00234 statusA.cbSize = sizeof(statusA); 00235 statusA.FileName = strdupWtoA( statusW->FileName ); 00236 statusA.Win32Error = statusW->Win32Error; 00237 statusA.FailureCode = statusW->FailureCode; 00238 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, 00239 (UINT_PTR)&statusA, param2 ); 00240 HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName ); 00241 } 00242 break; 00243 00244 case SPFILENOTIFY_QUEUESCAN: 00245 { 00246 LPWSTR targetW = (LPWSTR)param1; 00247 LPSTR target = strdupWtoA( targetW ); 00248 00249 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, 00250 (UINT_PTR)target, param2 ); 00251 HeapFree( GetProcessHeap(), 0, target ); 00252 } 00253 break; 00254 00255 case SPFILENOTIFY_NEEDMEDIA: 00256 FIXME("mapping for %d not implemented\n",notification); 00257 case SPFILENOTIFY_STARTQUEUE: 00258 case SPFILENOTIFY_ENDQUEUE: 00259 case SPFILENOTIFY_STARTSUBQUEUE: 00260 case SPFILENOTIFY_ENDSUBQUEUE: 00261 default: 00262 ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 ); 00263 break; 00264 } 00265 return ret; 00266 } 00267 00268 00269 /*********************************************************************** 00270 * get_src_file_info 00271 * 00272 * Retrieve the source file information for a given file. 00273 */ 00274 static void get_src_file_info( HINF hinf, struct file_op *op ) 00275 { 00276 static const WCHAR SourceDisksNames[] = 00277 {'S','o','u','r','c','e','D','i','s','k','s','N','a','m','e','s',0}; 00278 static const WCHAR SourceDisksFiles[] = 00279 {'S','o','u','r','c','e','D','i','s','k','s','F','i','l','e','s',0}; 00280 00281 INFCONTEXT file_ctx, disk_ctx; 00282 INT id, diskid; 00283 DWORD len, len2; 00284 00285 /* find the SourceDisksFiles entry */ 00286 if (!SetupFindFirstLineW( hinf, SourceDisksFiles, op->src_file, &file_ctx )) 00287 { 00288 if ((op->style & (SP_COPY_SOURCE_ABSOLUTE|SP_COPY_SOURCEPATH_ABSOLUTE))) return; 00289 /* no specific info, use .inf file source directory */ 00290 if (!op->src_root) op->src_root = PARSER_get_src_root( hinf ); 00291 return; 00292 } 00293 if (!SetupGetIntField( &file_ctx, 1, &diskid )) return; 00294 00295 /* now find the diskid in the SourceDisksNames section */ 00296 if (!SetupFindFirstLineW( hinf, SourceDisksNames, NULL, &disk_ctx )) return; 00297 for (;;) 00298 { 00299 if (SetupGetIntField( &disk_ctx, 0, &id ) && (id == diskid)) break; 00300 if (!SetupFindNextLine( &disk_ctx, &disk_ctx )) return; 00301 } 00302 00303 /* and fill in the missing info */ 00304 00305 if (!op->src_descr) 00306 { 00307 if (SetupGetStringFieldW( &disk_ctx, 1, NULL, 0, &len ) && 00308 (op->src_descr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ))) 00309 SetupGetStringFieldW( &disk_ctx, 1, op->src_descr, len, NULL ); 00310 } 00311 if (!op->src_tag) 00312 { 00313 if (SetupGetStringFieldW( &disk_ctx, 2, NULL, 0, &len ) && 00314 (op->src_tag = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ))) 00315 SetupGetStringFieldW( &disk_ctx, 2, op->src_tag, len, NULL ); 00316 } 00317 if (!op->src_path && !(op->style & SP_COPY_SOURCE_ABSOLUTE)) 00318 { 00319 len = len2 = 0; 00320 if (!(op->style & SP_COPY_SOURCEPATH_ABSOLUTE)) 00321 { 00322 /* retrieve relative path for this disk */ 00323 if (!SetupGetStringFieldW( &disk_ctx, 4, NULL, 0, &len )) len = 0; 00324 } 00325 /* retrieve relative path for this file */ 00326 if (!SetupGetStringFieldW( &file_ctx, 2, NULL, 0, &len2 )) len2 = 0; 00327 00328 if ((len || len2) && 00329 (op->src_path = HeapAlloc( GetProcessHeap(), 0, (len+len2)*sizeof(WCHAR) ))) 00330 { 00331 WCHAR *ptr = op->src_path; 00332 if (len) 00333 { 00334 SetupGetStringFieldW( &disk_ctx, 4, op->src_path, len, NULL ); 00335 ptr = op->src_path + strlenW(op->src_path); 00336 if (len2 && ptr > op->src_path && ptr[-1] != '\\') *ptr++ = '\\'; 00337 } 00338 if (!SetupGetStringFieldW( &file_ctx, 2, ptr, len2, NULL )) *ptr = 0; 00339 } 00340 } 00341 if (!op->src_root) op->src_root = PARSER_get_src_root(hinf); 00342 } 00343 00344 00345 /*********************************************************************** 00346 * get_destination_dir 00347 * 00348 * Retrieve the destination dir for a given section. 00349 */ 00350 static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section ) 00351 { 00352 static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0}; 00353 static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0}; 00354 INFCONTEXT context; 00355 00356 if (!SetupFindFirstLineW( hinf, Dest, section, &context ) && 00357 !SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL; 00358 return PARSER_get_dest_dir( &context ); 00359 } 00360 00361 00362 static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD ); 00363 00364 /*********************************************************************** 00365 * extract_cabinet_file 00366 * 00367 * Extract a file from a .cab file. 00368 */ 00369 static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root, 00370 const WCHAR *src, const WCHAR *dst ) 00371 { 00372 static const WCHAR extW[] = {'.','c','a','b',0}; 00373 static HMODULE advpack; 00374 00375 char *cab_path, *cab_file; 00376 int len = strlenW( cabinet ); 00377 00378 /* make sure the cabinet file has a .cab extension */ 00379 if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE; 00380 if (!pExtractFiles) 00381 { 00382 if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" ))) 00383 { 00384 ERR( "could not load advpack.dll\n" ); 00385 return FALSE; 00386 } 00387 if (!(pExtractFiles = (void *)GetProcAddress( advpack, "ExtractFiles" ))) 00388 { 00389 ERR( "could not find ExtractFiles in advpack.dll\n" ); 00390 return FALSE; 00391 } 00392 } 00393 00394 if (!(cab_path = strdupWtoA( root ))) return FALSE; 00395 len = WideCharToMultiByte( CP_ACP, 0, cabinet, -1, NULL, 0, NULL, NULL ); 00396 if (!(cab_file = HeapAlloc( GetProcessHeap(), 0, strlen(cab_path) + len + 1 ))) 00397 { 00398 HeapFree( GetProcessHeap(), 0, cab_path ); 00399 return FALSE; 00400 } 00401 strcpy( cab_file, cab_path ); 00402 if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" ); 00403 WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL ); 00404 FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) ); 00405 pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 ); 00406 HeapFree( GetProcessHeap(), 0, cab_file ); 00407 HeapFree( GetProcessHeap(), 0, cab_path ); 00408 return CopyFileW( src, dst, FALSE /*FIXME*/ ); 00409 } 00410 00411 00412 /*********************************************************************** 00413 * SetupOpenFileQueue (SETUPAPI.@) 00414 */ 00415 HSPFILEQ WINAPI SetupOpenFileQueue(void) 00416 { 00417 struct file_queue *queue; 00418 00419 if (!(queue = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*queue)))) 00420 return INVALID_HANDLE_VALUE; 00421 return queue; 00422 } 00423 00424 00425 /*********************************************************************** 00426 * SetupCloseFileQueue (SETUPAPI.@) 00427 */ 00428 BOOL WINAPI SetupCloseFileQueue( HSPFILEQ handle ) 00429 { 00430 struct file_queue *queue = handle; 00431 00432 free_file_op_queue( &queue->copy_queue ); 00433 free_file_op_queue( &queue->rename_queue ); 00434 free_file_op_queue( &queue->delete_queue ); 00435 HeapFree( GetProcessHeap(), 0, queue ); 00436 return TRUE; 00437 } 00438 00439 00440 /*********************************************************************** 00441 * SetupQueueCopyIndirectA (SETUPAPI.@) 00442 */ 00443 BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A params ) 00444 { 00445 struct file_queue *queue = params->QueueHandle; 00446 struct file_op *op; 00447 00448 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 00449 op->style = params->CopyStyle; 00450 op->src_root = strdupAtoW( params->SourceRootPath ); 00451 op->src_path = strdupAtoW( params->SourcePath ); 00452 op->src_file = strdupAtoW( params->SourceFilename ); 00453 op->src_descr = strdupAtoW( params->SourceDescription ); 00454 op->src_tag = strdupAtoW( params->SourceTagfile ); 00455 op->dst_path = strdupAtoW( params->TargetDirectory ); 00456 op->dst_file = strdupAtoW( params->TargetFilename ); 00457 00458 /* some defaults */ 00459 if (!op->src_file) op->src_file = op->dst_file; 00460 if (params->LayoutInf) 00461 { 00462 get_src_file_info( params->LayoutInf, op ); 00463 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file ); 00464 } 00465 00466 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n", 00467 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file), 00468 debugstr_w(op->dst_path), debugstr_w(op->dst_file), 00469 debugstr_w(op->src_descr), debugstr_w(op->src_tag) ); 00470 00471 queue_file_op( &queue->copy_queue, op ); 00472 return TRUE; 00473 } 00474 00475 00476 /*********************************************************************** 00477 * SetupQueueCopyIndirectW (SETUPAPI.@) 00478 */ 00479 BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W params ) 00480 { 00481 struct file_queue *queue = params->QueueHandle; 00482 struct file_op *op; 00483 00484 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 00485 op->style = params->CopyStyle; 00486 op->src_root = strdupW( params->SourceRootPath ); 00487 op->src_path = strdupW( params->SourcePath ); 00488 op->src_file = strdupW( params->SourceFilename ); 00489 op->src_descr = strdupW( params->SourceDescription ); 00490 op->src_tag = strdupW( params->SourceTagfile ); 00491 op->dst_path = strdupW( params->TargetDirectory ); 00492 op->dst_file = strdupW( params->TargetFilename ); 00493 op->dst_sd = NULL; 00494 if (params->SecurityDescriptor) 00495 ConvertStringSecurityDescriptorToSecurityDescriptorW( params->SecurityDescriptor, SDDL_REVISION_1, &op->dst_sd, NULL ); 00496 00497 /* some defaults */ 00498 if (!op->src_file) op->src_file = op->dst_file; 00499 if (params->LayoutInf) 00500 { 00501 get_src_file_info( params->LayoutInf, op ); 00502 if (!op->dst_path) op->dst_path = get_destination_dir( params->LayoutInf, op->dst_file ); 00503 } 00504 00505 TRACE( "root=%s path=%s file=%s -> dir=%s file=%s descr=%s tag=%s\n", 00506 debugstr_w(op->src_root), debugstr_w(op->src_path), debugstr_w(op->src_file), 00507 debugstr_w(op->dst_path), debugstr_w(op->dst_file), 00508 debugstr_w(op->src_descr), debugstr_w(op->src_tag) ); 00509 00510 queue_file_op( &queue->copy_queue, op ); 00511 return TRUE; 00512 } 00513 00514 00515 /*********************************************************************** 00516 * SetupQueueCopyA (SETUPAPI.@) 00517 */ 00518 BOOL WINAPI SetupQueueCopyA( HSPFILEQ queue, PCSTR src_root, PCSTR src_path, PCSTR src_file, 00519 PCSTR src_descr, PCSTR src_tag, PCSTR dst_dir, PCSTR dst_file, 00520 DWORD style ) 00521 { 00522 SP_FILE_COPY_PARAMS_A params; 00523 00524 params.cbSize = sizeof(params); 00525 params.QueueHandle = queue; 00526 params.SourceRootPath = src_root; 00527 params.SourcePath = src_path; 00528 params.SourceFilename = src_file; 00529 params.SourceDescription = src_descr; 00530 params.SourceTagfile = src_tag; 00531 params.TargetDirectory = dst_dir; 00532 params.TargetFilename = dst_file; 00533 params.CopyStyle = style; 00534 params.LayoutInf = 0; 00535 params.SecurityDescriptor = NULL; 00536 return SetupQueueCopyIndirectA( ¶ms ); 00537 } 00538 00539 00540 /*********************************************************************** 00541 * SetupQueueCopyW (SETUPAPI.@) 00542 */ 00543 BOOL WINAPI SetupQueueCopyW( HSPFILEQ queue, PCWSTR src_root, PCWSTR src_path, PCWSTR src_file, 00544 PCWSTR src_descr, PCWSTR src_tag, PCWSTR dst_dir, PCWSTR dst_file, 00545 DWORD style ) 00546 { 00547 SP_FILE_COPY_PARAMS_W params; 00548 00549 params.cbSize = sizeof(params); 00550 params.QueueHandle = queue; 00551 params.SourceRootPath = src_root; 00552 params.SourcePath = src_path; 00553 params.SourceFilename = src_file; 00554 params.SourceDescription = src_descr; 00555 params.SourceTagfile = src_tag; 00556 params.TargetDirectory = dst_dir; 00557 params.TargetFilename = dst_file; 00558 params.CopyStyle = style; 00559 params.LayoutInf = 0; 00560 params.SecurityDescriptor = NULL; 00561 return SetupQueueCopyIndirectW( ¶ms ); 00562 } 00563 00564 00565 /*********************************************************************** 00566 * SetupQueueDefaultCopyA (SETUPAPI.@) 00567 */ 00568 BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ queue, HINF hinf, PCSTR src_root, PCSTR src_file, 00569 PCSTR dst_file, DWORD style ) 00570 { 00571 SP_FILE_COPY_PARAMS_A params; 00572 00573 params.cbSize = sizeof(params); 00574 params.QueueHandle = queue; 00575 params.SourceRootPath = src_root; 00576 params.SourcePath = NULL; 00577 params.SourceFilename = src_file; 00578 params.SourceDescription = NULL; 00579 params.SourceTagfile = NULL; 00580 params.TargetDirectory = NULL; 00581 params.TargetFilename = dst_file; 00582 params.CopyStyle = style; 00583 params.LayoutInf = hinf; 00584 params.SecurityDescriptor = NULL; 00585 return SetupQueueCopyIndirectA( ¶ms ); 00586 } 00587 00588 00589 /*********************************************************************** 00590 * SetupQueueDefaultCopyW (SETUPAPI.@) 00591 */ 00592 BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ queue, HINF hinf, PCWSTR src_root, PCWSTR src_file, 00593 PCWSTR dst_file, DWORD style ) 00594 { 00595 SP_FILE_COPY_PARAMS_W params; 00596 00597 params.cbSize = sizeof(params); 00598 params.QueueHandle = queue; 00599 params.SourceRootPath = src_root; 00600 params.SourcePath = NULL; 00601 params.SourceFilename = src_file; 00602 params.SourceDescription = NULL; 00603 params.SourceTagfile = NULL; 00604 params.TargetDirectory = NULL; 00605 params.TargetFilename = dst_file; 00606 params.CopyStyle = style; 00607 params.LayoutInf = hinf; 00608 params.SecurityDescriptor = NULL; 00609 return SetupQueueCopyIndirectW( ¶ms ); 00610 } 00611 00612 00613 /*********************************************************************** 00614 * SetupQueueDeleteA (SETUPAPI.@) 00615 */ 00616 BOOL WINAPI SetupQueueDeleteA( HSPFILEQ handle, PCSTR part1, PCSTR part2 ) 00617 { 00618 struct file_queue *queue = handle; 00619 struct file_op *op; 00620 00621 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 00622 op->style = 0; 00623 op->src_root = NULL; 00624 op->src_path = NULL; 00625 op->src_file = NULL; 00626 op->src_descr = NULL; 00627 op->src_tag = NULL; 00628 op->dst_path = strdupAtoW( part1 ); 00629 op->dst_file = strdupAtoW( part2 ); 00630 queue_file_op( &queue->delete_queue, op ); 00631 return TRUE; 00632 } 00633 00634 00635 /*********************************************************************** 00636 * SetupQueueDeleteW (SETUPAPI.@) 00637 */ 00638 BOOL WINAPI SetupQueueDeleteW( HSPFILEQ handle, PCWSTR part1, PCWSTR part2 ) 00639 { 00640 struct file_queue *queue = handle; 00641 struct file_op *op; 00642 00643 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 00644 op->style = 0; 00645 op->src_root = NULL; 00646 op->src_path = NULL; 00647 op->src_file = NULL; 00648 op->src_descr = NULL; 00649 op->src_tag = NULL; 00650 op->dst_path = strdupW( part1 ); 00651 op->dst_file = strdupW( part2 ); 00652 queue_file_op( &queue->delete_queue, op ); 00653 return TRUE; 00654 } 00655 00656 00657 /*********************************************************************** 00658 * SetupQueueRenameA (SETUPAPI.@) 00659 */ 00660 BOOL WINAPI SetupQueueRenameA( HSPFILEQ handle, PCSTR SourcePath, PCSTR SourceFilename, 00661 PCSTR TargetPath, PCSTR TargetFilename ) 00662 { 00663 struct file_queue *queue = handle; 00664 struct file_op *op; 00665 00666 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 00667 op->style = 0; 00668 op->src_root = NULL; 00669 op->src_path = strdupAtoW( SourcePath ); 00670 op->src_file = strdupAtoW( SourceFilename ); 00671 op->src_descr = NULL; 00672 op->src_tag = NULL; 00673 op->dst_path = strdupAtoW( TargetPath ); 00674 op->dst_file = strdupAtoW( TargetFilename ); 00675 queue_file_op( &queue->rename_queue, op ); 00676 return TRUE; 00677 } 00678 00679 00680 /*********************************************************************** 00681 * SetupQueueRenameW (SETUPAPI.@) 00682 */ 00683 BOOL WINAPI SetupQueueRenameW( HSPFILEQ handle, PCWSTR SourcePath, PCWSTR SourceFilename, 00684 PCWSTR TargetPath, PCWSTR TargetFilename ) 00685 { 00686 struct file_queue *queue = handle; 00687 struct file_op *op; 00688 00689 if (!(op = HeapAlloc( GetProcessHeap(), 0, sizeof(*op) ))) return FALSE; 00690 op->style = 0; 00691 op->src_root = NULL; 00692 op->src_path = strdupW( SourcePath ); 00693 op->src_file = strdupW( SourceFilename ); 00694 op->src_descr = NULL; 00695 op->src_tag = NULL; 00696 op->dst_path = strdupW( TargetPath ); 00697 op->dst_file = strdupW( TargetFilename ); 00698 queue_file_op( &queue->rename_queue, op ); 00699 return TRUE; 00700 } 00701 00702 00703 /*********************************************************************** 00704 * SetupQueueCopySectionA (SETUPAPI.@) 00705 */ 00706 BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ queue, PCSTR src_root, HINF hinf, HINF hlist, 00707 PCSTR section, DWORD style ) 00708 { 00709 UNICODE_STRING sectionW; 00710 BOOL ret = FALSE; 00711 00712 if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section )) 00713 { 00714 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 00715 return FALSE; 00716 } 00717 if (!src_root) 00718 ret = SetupQueueCopySectionW( queue, NULL, hinf, hlist, sectionW.Buffer, style ); 00719 else 00720 { 00721 UNICODE_STRING srcW; 00722 if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root )) 00723 { 00724 ret = SetupQueueCopySectionW( queue, srcW.Buffer, hinf, hlist, sectionW.Buffer, style ); 00725 RtlFreeUnicodeString( &srcW ); 00726 } 00727 else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 00728 } 00729 RtlFreeUnicodeString( §ionW ); 00730 return ret; 00731 } 00732 00733 00734 /*********************************************************************** 00735 * SetupQueueCopySectionW (SETUPAPI.@) 00736 */ 00737 BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ queue, PCWSTR src_root, HINF hinf, HINF hlist, 00738 PCWSTR section, DWORD style ) 00739 { 00740 SP_FILE_COPY_PARAMS_W params; 00741 LPWSTR security_key, security_descriptor = NULL; 00742 INFCONTEXT context, security_context; 00743 WCHAR dest[MAX_PATH], src[MAX_PATH]; 00744 INT flags; 00745 DWORD required; 00746 BOOL ret; 00747 00748 TRACE( "hinf=%p/%p section=%s root=%s\n", 00749 hinf, hlist, debugstr_w(section), debugstr_w(src_root) ); 00750 00751 /* Check for .Security section */ 00752 security_key = MyMalloc( (strlenW( section ) + strlenW( DotSecurity )) * sizeof(WCHAR) + sizeof(UNICODE_NULL) ); 00753 if (!security_key) 00754 { 00755 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00756 return FALSE; 00757 } 00758 strcpyW( security_key, section ); 00759 strcatW( security_key, DotSecurity ); 00760 ret = SetupFindFirstLineW( hinf, security_key, NULL, &security_context ); 00761 MyFree(security_key); 00762 if (ret) 00763 { 00764 if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, NULL, 0, &required )) 00765 return FALSE; 00766 security_descriptor = MyMalloc( required * sizeof(WCHAR) ); 00767 if (!security_descriptor) 00768 { 00769 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00770 return FALSE; 00771 } 00772 if (!SetupGetLineTextW( &security_context, NULL, NULL, NULL, security_descriptor, required, NULL )) 00773 { 00774 MyFree( security_descriptor ); 00775 return FALSE; 00776 } 00777 } 00778 00779 params.cbSize = sizeof(params); 00780 params.QueueHandle = queue; 00781 params.SourceRootPath = src_root; 00782 params.SourcePath = NULL; 00783 params.SourceDescription = NULL; 00784 params.SourceTagfile = NULL; 00785 params.TargetFilename = dest; 00786 params.CopyStyle = style; 00787 params.LayoutInf = hinf; 00788 params.SecurityDescriptor = security_descriptor; 00789 00790 ret = FALSE; 00791 if (!hlist) hlist = hinf; 00792 if (!hinf) hinf = hlist; 00793 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) goto done; 00794 if (!(params.TargetDirectory = get_destination_dir( hinf, section ))) goto done; 00795 do 00796 { 00797 if (!SetupGetStringFieldW( &context, 1, dest, sizeof(dest)/sizeof(WCHAR), NULL )) 00798 goto done; 00799 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) *src = 0; 00800 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; /* FIXME */ 00801 00802 params.SourceFilename = *src ? src : NULL; 00803 if (!SetupQueueCopyIndirectW( ¶ms )) goto done; 00804 } while (SetupFindNextLine( &context, &context )); 00805 ret = TRUE; 00806 00807 done: 00808 if (security_descriptor) 00809 MyFree( security_descriptor ); 00810 return ret; 00811 } 00812 00813 00814 /*********************************************************************** 00815 * SetupQueueDeleteSectionA (SETUPAPI.@) 00816 */ 00817 BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section ) 00818 { 00819 UNICODE_STRING sectionW; 00820 BOOL ret = FALSE; 00821 00822 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) 00823 { 00824 ret = SetupQueueDeleteSectionW( queue, hinf, hlist, sectionW.Buffer ); 00825 RtlFreeUnicodeString( §ionW ); 00826 } 00827 else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 00828 return ret; 00829 } 00830 00831 00832 /*********************************************************************** 00833 * SetupQueueDeleteSectionW (SETUPAPI.@) 00834 */ 00835 BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section ) 00836 { 00837 INFCONTEXT context; 00838 WCHAR *dest_dir; 00839 WCHAR buffer[MAX_PATH]; 00840 BOOL ret = FALSE; 00841 INT flags; 00842 00843 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) ); 00844 00845 if (!hlist) hlist = hinf; 00846 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; 00847 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE; 00848 do 00849 { 00850 if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL )) 00851 goto done; 00852 if (!SetupGetIntField( &context, 4, &flags )) flags = 0; 00853 if (!SetupQueueDeleteW( queue, dest_dir, buffer )) goto done; 00854 } while (SetupFindNextLine( &context, &context )); 00855 00856 ret = TRUE; 00857 done: 00858 HeapFree( GetProcessHeap(), 0, dest_dir ); 00859 return ret; 00860 } 00861 00862 00863 /*********************************************************************** 00864 * SetupQueueRenameSectionA (SETUPAPI.@) 00865 */ 00866 BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ queue, HINF hinf, HINF hlist, PCSTR section ) 00867 { 00868 UNICODE_STRING sectionW; 00869 BOOL ret = FALSE; 00870 00871 if (RtlCreateUnicodeStringFromAsciiz( §ionW, section )) 00872 { 00873 ret = SetupQueueRenameSectionW( queue, hinf, hlist, sectionW.Buffer ); 00874 RtlFreeUnicodeString( §ionW ); 00875 } 00876 else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 00877 return ret; 00878 } 00879 00880 00881 /*********************************************************************** 00882 * SetupQueueRenameSectionW (SETUPAPI.@) 00883 */ 00884 BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ queue, HINF hinf, HINF hlist, PCWSTR section ) 00885 { 00886 INFCONTEXT context; 00887 WCHAR *dest_dir; 00888 WCHAR src[MAX_PATH], dst[MAX_PATH]; 00889 BOOL ret = FALSE; 00890 00891 TRACE( "hinf=%p/%p section=%s\n", hinf, hlist, debugstr_w(section) ); 00892 00893 if (!hlist) hlist = hinf; 00894 if (!SetupFindFirstLineW( hlist, section, NULL, &context )) return FALSE; 00895 if (!(dest_dir = get_destination_dir( hinf, section ))) return FALSE; 00896 do 00897 { 00898 if (!SetupGetStringFieldW( &context, 1, dst, sizeof(dst)/sizeof(WCHAR), NULL )) 00899 goto done; 00900 if (!SetupGetStringFieldW( &context, 2, src, sizeof(src)/sizeof(WCHAR), NULL )) 00901 goto done; 00902 if (!SetupQueueRenameW( queue, dest_dir, src, NULL, dst )) goto done; 00903 } while (SetupFindNextLine( &context, &context )); 00904 00905 ret = TRUE; 00906 done: 00907 HeapFree( GetProcessHeap(), 0, dest_dir ); 00908 return ret; 00909 } 00910 00911 00912 /*********************************************************************** 00913 * SetupCommitFileQueueA (SETUPAPI.@) 00914 */ 00915 BOOL WINAPI SetupCommitFileQueueA( HWND owner, HSPFILEQ queue, PSP_FILE_CALLBACK_A handler, 00916 PVOID context ) 00917 { 00918 struct callback_WtoA_context ctx; 00919 00920 ctx.orig_context = context; 00921 ctx.orig_handler = handler; 00922 return SetupCommitFileQueueW( owner, queue, QUEUE_callback_WtoA, &ctx ); 00923 } 00924 00925 00926 /*********************************************************************** 00927 * create_full_pathW 00928 * 00929 * Recursively create all directories in the path. 00930 */ 00931 static BOOL create_full_pathW(const WCHAR *path) 00932 { 00933 BOOL ret = TRUE; 00934 int len; 00935 WCHAR *new_path; 00936 00937 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR)); 00938 strcpyW(new_path, path); 00939 00940 while((len = strlenW(new_path)) && new_path[len - 1] == '\\') 00941 new_path[len - 1] = 0; 00942 00943 while(!CreateDirectoryW(new_path, NULL)) 00944 { 00945 WCHAR *slash; 00946 DWORD last_error = GetLastError(); 00947 00948 if(last_error == ERROR_ALREADY_EXISTS) 00949 break; 00950 00951 if(last_error != ERROR_PATH_NOT_FOUND) 00952 { 00953 ret = FALSE; 00954 break; 00955 } 00956 00957 if(!(slash = strrchrW(new_path, '\\'))) 00958 { 00959 ret = FALSE; 00960 break; 00961 } 00962 00963 len = slash - new_path; 00964 new_path[len] = 0; 00965 if(!create_full_pathW(new_path)) 00966 { 00967 ret = FALSE; 00968 break; 00969 } 00970 new_path[len] = '\\'; 00971 } 00972 00973 HeapFree(GetProcessHeap(), 0, new_path); 00974 return ret; 00975 } 00976 00977 static BOOL do_file_copyW( LPCWSTR source, LPCWSTR target, DWORD style, 00978 PSP_FILE_CALLBACK_W handler, PVOID context ) 00979 { 00980 BOOL rc = FALSE; 00981 BOOL docopy = TRUE; 00982 00983 TRACE("copy %s to %s style 0x%x\n",debugstr_w(source),debugstr_w(target),style); 00984 00985 /* before copy processing */ 00986 if (style & SP_COPY_REPLACEONLY) 00987 { 00988 if (GetFileAttributesW(target) == INVALID_FILE_ATTRIBUTES) 00989 docopy = FALSE; 00990 } 00991 if (style & (SP_COPY_NEWER_OR_SAME | SP_COPY_NEWER_ONLY | SP_COPY_FORCE_NEWER)) 00992 { 00993 DWORD VersionSizeSource=0; 00994 DWORD VersionSizeTarget=0; 00995 DWORD zero=0; 00996 00997 /* 00998 * This is sort of an interesting workaround. You see, calling 00999 * GetVersionInfoSize on a builtin dll loads that dll into memory 01000 * and we do not properly unload builtin dlls.. so we effectively 01001 * lock into memory all the targets we are replacing. This leads 01002 * to problems when we try to register the replaced dlls. 01003 * 01004 * So I will test for the existence of the files first so that 01005 * we just basically unconditionally replace the builtin versions. 01006 */ 01007 if ((GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) && 01008 (GetFileAttributesW(source) != INVALID_FILE_ATTRIBUTES)) 01009 { 01010 VersionSizeSource = GetFileVersionInfoSizeW((LPWSTR)source,&zero); 01011 VersionSizeTarget = GetFileVersionInfoSizeW((LPWSTR)target,&zero); 01012 } 01013 01014 TRACE("SizeTarget %i ... SizeSource %i\n",VersionSizeTarget, 01015 VersionSizeSource); 01016 01017 if (VersionSizeSource && VersionSizeTarget) 01018 { 01019 LPVOID VersionSource; 01020 LPVOID VersionTarget; 01021 VS_FIXEDFILEINFO *TargetInfo; 01022 VS_FIXEDFILEINFO *SourceInfo; 01023 UINT length; 01024 WCHAR SubBlock[2]={'\\',0}; 01025 DWORD ret; 01026 01027 VersionSource = HeapAlloc(GetProcessHeap(),0,VersionSizeSource); 01028 VersionTarget = HeapAlloc(GetProcessHeap(),0,VersionSizeTarget); 01029 01030 ret = GetFileVersionInfoW((LPWSTR)source,0,VersionSizeSource,VersionSource); 01031 if (ret) 01032 ret = GetFileVersionInfoW((LPWSTR)target, 0, VersionSizeTarget, 01033 VersionTarget); 01034 01035 if (ret) 01036 { 01037 ret = VerQueryValueW(VersionSource, SubBlock, 01038 (LPVOID*)&SourceInfo, &length); 01039 if (ret) 01040 ret = VerQueryValueW(VersionTarget, SubBlock, 01041 (LPVOID*)&TargetInfo, &length); 01042 01043 if (ret) 01044 { 01045 FILEPATHS_W filepaths; 01046 01047 TRACE("Versions: Source %i.%i target %i.%i\n", 01048 SourceInfo->dwFileVersionMS, SourceInfo->dwFileVersionLS, 01049 TargetInfo->dwFileVersionMS, TargetInfo->dwFileVersionLS); 01050 01051 /* used in case of notification */ 01052 filepaths.Target = target; 01053 filepaths.Source = source; 01054 filepaths.Win32Error = 0; 01055 filepaths.Flags = 0; 01056 01057 if (TargetInfo->dwFileVersionMS > SourceInfo->dwFileVersionMS) 01058 { 01059 if (handler) 01060 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0); 01061 else 01062 docopy = FALSE; 01063 } 01064 else if ((TargetInfo->dwFileVersionMS == SourceInfo->dwFileVersionMS) 01065 && (TargetInfo->dwFileVersionLS > SourceInfo->dwFileVersionLS)) 01066 { 01067 if (handler) 01068 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0); 01069 else 01070 docopy = FALSE; 01071 } 01072 else if ((style & SP_COPY_NEWER_ONLY) && 01073 (TargetInfo->dwFileVersionMS == 01074 SourceInfo->dwFileVersionMS) 01075 &&(TargetInfo->dwFileVersionLS == 01076 SourceInfo->dwFileVersionLS)) 01077 { 01078 if (handler) 01079 docopy = handler (context, SPFILENOTIFY_TARGETNEWER, (UINT_PTR)&filepaths, 0); 01080 else 01081 docopy = FALSE; 01082 } 01083 } 01084 } 01085 HeapFree(GetProcessHeap(),0,VersionSource); 01086 HeapFree(GetProcessHeap(),0,VersionTarget); 01087 } 01088 } 01089 if (style & (SP_COPY_NOOVERWRITE | SP_COPY_FORCE_NOOVERWRITE)) 01090 { 01091 if (GetFileAttributesW(target) != INVALID_FILE_ATTRIBUTES) 01092 { 01093 FIXME("Notify user target file exists\n"); 01094 docopy = FALSE; 01095 } 01096 } 01097 if (style & (SP_COPY_NODECOMP | SP_COPY_LANGUAGEAWARE | SP_COPY_FORCE_IN_USE | 01098 SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP | SP_COPY_WARNIFSKIP)) 01099 { 01100 ERR("Unsupported style(s) 0x%x\n",style); 01101 } 01102 01103 if (docopy) 01104 { 01105 rc = CopyFileW(source,target,FALSE); 01106 TRACE("Did copy... rc was %i\n",rc); 01107 } 01108 01109 /* after copy processing */ 01110 if (style & SP_COPY_DELETESOURCE) 01111 { 01112 if (rc) 01113 DeleteFileW(source); 01114 } 01115 01116 return rc; 01117 } 01118 01119 /*********************************************************************** 01120 * SetupInstallFileA (SETUPAPI.@) 01121 */ 01122 BOOL WINAPI SetupInstallFileA( HINF hinf, PINFCONTEXT inf_context, PCSTR source, PCSTR root, 01123 PCSTR dest, DWORD style, PSP_FILE_CALLBACK_A handler, PVOID context ) 01124 { 01125 BOOL ret = FALSE; 01126 struct callback_WtoA_context ctx; 01127 UNICODE_STRING sourceW, rootW, destW; 01128 01129 TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_a(source), debugstr_a(root), 01130 debugstr_a(dest), style, handler, context); 01131 01132 sourceW.Buffer = rootW.Buffer = destW.Buffer = NULL; 01133 if (source && !RtlCreateUnicodeStringFromAsciiz( &sourceW, source )) 01134 { 01135 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 01136 return FALSE; 01137 } 01138 if (root && !RtlCreateUnicodeStringFromAsciiz( &rootW, root )) 01139 { 01140 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 01141 goto exit; 01142 } 01143 if (dest && !RtlCreateUnicodeStringFromAsciiz( &destW, dest )) 01144 { 01145 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 01146 goto exit; 01147 } 01148 01149 ctx.orig_context = context; 01150 ctx.orig_handler = handler; 01151 01152 ret = SetupInstallFileW( hinf, inf_context, sourceW.Buffer, rootW.Buffer, destW.Buffer, style, QUEUE_callback_WtoA, &ctx ); 01153 01154 exit: 01155 RtlFreeUnicodeString( &sourceW ); 01156 RtlFreeUnicodeString( &rootW ); 01157 RtlFreeUnicodeString( &destW ); 01158 return ret; 01159 } 01160 01161 /*********************************************************************** 01162 * SetupInstallFileW (SETUPAPI.@) 01163 */ 01164 BOOL WINAPI SetupInstallFileW( HINF hinf, PINFCONTEXT inf_context, PCWSTR source, PCWSTR root, 01165 PCWSTR dest, DWORD style, PSP_FILE_CALLBACK_W handler, PVOID context ) 01166 { 01167 static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0}; 01168 01169 BOOL ret, absolute = (root && *root && !(style & SP_COPY_SOURCE_ABSOLUTE)); 01170 WCHAR *buffer, *p, *inf_source = NULL; 01171 unsigned int len; 01172 01173 TRACE("%p %p %s %s %s %x %p %p\n", hinf, inf_context, debugstr_w(source), debugstr_w(root), 01174 debugstr_w(dest), style, handler, context); 01175 01176 if (hinf) 01177 { 01178 INFCONTEXT ctx; 01179 01180 if (!inf_context) 01181 { 01182 inf_context = &ctx; 01183 if (!SetupFindFirstLineW( hinf, CopyFiles, NULL, inf_context )) return FALSE; 01184 } 01185 if (!SetupGetStringFieldW( inf_context, 1, NULL, 0, (PDWORD) &len )) return FALSE; 01186 if (!(inf_source = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 01187 { 01188 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 01189 return FALSE; 01190 } 01191 if (!SetupGetStringFieldW( inf_context, 1, inf_source, len, NULL )) return FALSE; 01192 source = inf_source; 01193 } 01194 else if (!source) 01195 { 01196 SetLastError( ERROR_INVALID_PARAMETER ); 01197 return FALSE; 01198 } 01199 01200 len = strlenW( source ) + 1; 01201 if (absolute) len += strlenW( root ) + 1; 01202 01203 if (!(p = buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 01204 { 01205 HeapFree( GetProcessHeap(), 0, inf_source ); 01206 SetLastError( ERROR_NOT_ENOUGH_MEMORY ); 01207 return FALSE; 01208 } 01209 01210 if (absolute) 01211 { 01212 strcpyW( buffer, root ); 01213 p += strlenW( buffer ); 01214 if (p[-1] != '\\') *p++ = '\\'; 01215 } 01216 while (*source == '\\') source++; 01217 strcpyW( p, source ); 01218 01219 ret = do_file_copyW( buffer, dest, style, handler, context ); 01220 01221 HeapFree( GetProcessHeap(), 0, inf_source ); 01222 HeapFree( GetProcessHeap(), 0, buffer ); 01223 return ret; 01224 } 01225 01226 /*********************************************************************** 01227 * SetupCommitFileQueueW (SETUPAPI.@) 01228 */ 01229 BOOL WINAPI SetupCommitFileQueueW( HWND owner, HSPFILEQ handle, PSP_FILE_CALLBACK_W handler, 01230 PVOID context ) 01231 { 01232 struct file_queue *queue = handle; 01233 struct file_op *op; 01234 BOOL result = FALSE; 01235 FILEPATHS_W paths; 01236 UINT op_result; 01237 01238 paths.Source = paths.Target = NULL; 01239 01240 if (!queue->copy_queue.count && !queue->delete_queue.count && !queue->rename_queue.count) 01241 return TRUE; /* nothing to do */ 01242 01243 if (!handler( context, SPFILENOTIFY_STARTQUEUE, (UINT_PTR)owner, 0 )) return FALSE; 01244 01245 /* perform deletes */ 01246 01247 if (queue->delete_queue.count) 01248 { 01249 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_DELETE, 01250 queue->delete_queue.count ))) goto done; 01251 for (op = queue->delete_queue.head; op; op = op->next) 01252 { 01253 build_filepathsW( op, &paths ); 01254 op_result = handler( context, SPFILENOTIFY_STARTDELETE, (UINT_PTR)&paths, FILEOP_DELETE); 01255 if (op_result == FILEOP_ABORT) goto done; 01256 while (op_result == FILEOP_DOIT) 01257 { 01258 TRACE( "deleting file %s\n", debugstr_w(paths.Target) ); 01259 if (DeleteFileW( paths.Target )) break; /* success */ 01260 paths.Win32Error = GetLastError(); 01261 op_result = handler( context, SPFILENOTIFY_DELETEERROR, (UINT_PTR)&paths, 0 ); 01262 if (op_result == FILEOP_ABORT) goto done; 01263 } 01264 handler( context, SPFILENOTIFY_ENDDELETE, (UINT_PTR)&paths, 0 ); 01265 } 01266 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_DELETE, 0 ); 01267 } 01268 01269 /* perform renames */ 01270 01271 if (queue->rename_queue.count) 01272 { 01273 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_RENAME, 01274 queue->rename_queue.count ))) goto done; 01275 for (op = queue->rename_queue.head; op; op = op->next) 01276 { 01277 build_filepathsW( op, &paths ); 01278 op_result = handler( context, SPFILENOTIFY_STARTRENAME, (UINT_PTR)&paths, FILEOP_RENAME); 01279 if (op_result == FILEOP_ABORT) goto done; 01280 while (op_result == FILEOP_DOIT) 01281 { 01282 TRACE( "renaming file %s -> %s\n", 01283 debugstr_w(paths.Source), debugstr_w(paths.Target) ); 01284 if (MoveFileW( paths.Source, paths.Target )) break; /* success */ 01285 paths.Win32Error = GetLastError(); 01286 op_result = handler( context, SPFILENOTIFY_RENAMEERROR, (UINT_PTR)&paths, 0 ); 01287 if (op_result == FILEOP_ABORT) goto done; 01288 } 01289 handler( context, SPFILENOTIFY_ENDRENAME, (UINT_PTR)&paths, 0 ); 01290 } 01291 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_RENAME, 0 ); 01292 } 01293 01294 /* perform copies */ 01295 01296 if (queue->copy_queue.count) 01297 { 01298 if (!(handler( context, SPFILENOTIFY_STARTSUBQUEUE, FILEOP_COPY, 01299 queue->copy_queue.count ))) goto done; 01300 for (op = queue->copy_queue.head; op; op = op->next) 01301 { 01302 WCHAR newpath[MAX_PATH]; 01303 01304 build_filepathsW( op, &paths ); 01305 op_result = handler( context, SPFILENOTIFY_STARTCOPY, (UINT_PTR)&paths, FILEOP_COPY ); 01306 if (op_result == FILEOP_ABORT) goto done; 01307 if (op_result == FILEOP_NEWPATH) op_result = FILEOP_DOIT; 01308 while (op_result == FILEOP_DOIT || op_result == FILEOP_NEWPATH) 01309 { 01310 TRACE( "copying file %s -> %s\n", 01311 debugstr_w( op_result == FILEOP_NEWPATH ? newpath : paths.Source ), 01312 debugstr_w(paths.Target) ); 01313 if (op->dst_path) 01314 { 01315 if (!create_full_pathW( op->dst_path )) 01316 { 01317 paths.Win32Error = GetLastError(); 01318 op_result = handler( context, SPFILENOTIFY_COPYERROR, 01319 (UINT_PTR)&paths, (UINT_PTR)newpath ); 01320 if (op_result == FILEOP_ABORT) goto done; 01321 } 01322 } 01323 if (do_file_copyW( op_result == FILEOP_NEWPATH ? newpath : paths.Source, 01324 paths.Target, op->style, handler, context )) break; /* success */ 01325 /* try to extract it from the cabinet file */ 01326 if (op->src_tag) 01327 { 01328 if (extract_cabinet_file( op->src_tag, op->src_root, 01329 paths.Source, paths.Target )) break; 01330 } 01331 paths.Win32Error = GetLastError(); 01332 op_result = handler( context, SPFILENOTIFY_COPYERROR, 01333 (UINT_PTR)&paths, (UINT_PTR)newpath ); 01334 if (op_result == FILEOP_ABORT) goto done; 01335 } 01336 if (op->dst_sd) 01337 { 01338 PSID psidOwner = NULL, psidGroup = NULL; 01339 PACL pDacl = NULL, pSacl = NULL; 01340 SECURITY_INFORMATION security_info = 0; 01341 BOOL present, dummy; 01342 01343 if (GetSecurityDescriptorOwner( op->dst_sd, &psidOwner, &dummy ) && psidOwner) 01344 security_info |= OWNER_SECURITY_INFORMATION; 01345 if (GetSecurityDescriptorGroup( op->dst_sd, &psidGroup, &dummy ) && psidGroup) 01346 security_info |= GROUP_SECURITY_INFORMATION; 01347 if (GetSecurityDescriptorDacl( op->dst_sd, &present, &pDacl, &dummy )) 01348 security_info |= DACL_SECURITY_INFORMATION; 01349 if (GetSecurityDescriptorSacl( op->dst_sd, &present, &pSacl, &dummy )) 01350 security_info |= DACL_SECURITY_INFORMATION; 01351 SetNamedSecurityInfoW( (LPWSTR)paths.Target, SE_FILE_OBJECT, security_info, 01352 psidOwner, psidGroup, pDacl, pSacl ); 01353 /* Yes, ignore the return code... */ 01354 } 01355 handler( context, SPFILENOTIFY_ENDCOPY, (UINT_PTR)&paths, 0 ); 01356 } 01357 handler( context, SPFILENOTIFY_ENDSUBQUEUE, FILEOP_COPY, 0 ); 01358 } 01359 01360 01361 result = TRUE; 01362 01363 done: 01364 handler( context, SPFILENOTIFY_ENDQUEUE, result, 0 ); 01365 HeapFree( GetProcessHeap(), 0, (void *)paths.Source ); 01366 HeapFree( GetProcessHeap(), 0, (void *)paths.Target ); 01367 return result; 01368 } 01369 01370 01371 /*********************************************************************** 01372 * SetupScanFileQueueA (SETUPAPI.@) 01373 */ 01374 BOOL WINAPI SetupScanFileQueueA( HSPFILEQ handle, DWORD flags, HWND window, 01375 PSP_FILE_CALLBACK_A handler, PVOID context, PDWORD result ) 01376 { 01377 struct callback_WtoA_context ctx; 01378 01379 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result); 01380 01381 ctx.orig_context = context; 01382 ctx.orig_handler = handler; 01383 01384 return SetupScanFileQueueW( handle, flags, window, QUEUE_callback_WtoA, &ctx, result ); 01385 } 01386 01387 01388 /*********************************************************************** 01389 * SetupScanFileQueueW (SETUPAPI.@) 01390 */ 01391 BOOL WINAPI SetupScanFileQueueW( HSPFILEQ handle, DWORD flags, HWND window, 01392 PSP_FILE_CALLBACK_W handler, PVOID context, PDWORD result ) 01393 { 01394 struct file_queue *queue = handle; 01395 struct file_op *op; 01396 FILEPATHS_W paths; 01397 UINT notification = 0; 01398 BOOL ret = FALSE; 01399 01400 TRACE("%p %x %p %p %p %p\n", handle, flags, window, handler, context, result); 01401 01402 *result = FALSE; 01403 01404 if (!queue->copy_queue.count) return TRUE; 01405 01406 if (flags & SPQ_SCAN_USE_CALLBACK) notification = SPFILENOTIFY_QUEUESCAN; 01407 else if (flags & SPQ_SCAN_USE_CALLBACKEX) notification = SPFILENOTIFY_QUEUESCAN_EX; 01408 01409 if (flags & ~(SPQ_SCAN_USE_CALLBACK | SPQ_SCAN_USE_CALLBACKEX)) 01410 { 01411 FIXME("flags %x not fully implemented\n", flags); 01412 } 01413 01414 paths.Source = paths.Target = NULL; 01415 01416 for (op = queue->copy_queue.head; op; op = op->next) 01417 { 01418 build_filepathsW( op, &paths ); 01419 switch (notification) 01420 { 01421 case SPFILENOTIFY_QUEUESCAN: 01422 /* FIXME: handle delay flag */ 01423 if (handler( context, notification, (UINT_PTR)paths.Target, 0 )) goto done; 01424 break; 01425 case SPFILENOTIFY_QUEUESCAN_EX: 01426 if (handler( context, notification, (UINT_PTR)&paths, 0 )) goto done; 01427 break; 01428 default: 01429 ret = TRUE; goto done; 01430 } 01431 } 01432 01433 *result = TRUE; 01434 01435 done: 01436 HeapFree( GetProcessHeap(), 0, (void *)paths.Source ); 01437 HeapFree( GetProcessHeap(), 0, (void *)paths.Target ); 01438 return ret; 01439 } 01440 01441 01442 /*********************************************************************** 01443 * SetupGetFileQueueCount (SETUPAPI.@) 01444 */ 01445 BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ handle, UINT op, PUINT result ) 01446 { 01447 struct file_queue *queue = handle; 01448 01449 switch(op) 01450 { 01451 case FILEOP_COPY: 01452 *result = queue->copy_queue.count; 01453 return TRUE; 01454 case FILEOP_RENAME: 01455 *result = queue->rename_queue.count; 01456 return TRUE; 01457 case FILEOP_DELETE: 01458 *result = queue->delete_queue.count; 01459 return TRUE; 01460 } 01461 return FALSE; 01462 } 01463 01464 01465 /*********************************************************************** 01466 * SetupGetFileQueueFlags (SETUPAPI.@) 01467 */ 01468 BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ handle, PDWORD flags ) 01469 { 01470 struct file_queue *queue = handle; 01471 *flags = queue->flags; 01472 return TRUE; 01473 } 01474 01475 01476 /*********************************************************************** 01477 * SetupSetFileQueueFlags (SETUPAPI.@) 01478 */ 01479 BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ handle, DWORD mask, DWORD flags ) 01480 { 01481 struct file_queue *queue = handle; 01482 queue->flags = (queue->flags & ~mask) | flags; 01483 return TRUE; 01484 } 01485 01486 01487 /*********************************************************************** 01488 * SetupSetFileQueueAlternatePlatformA (SETUPAPI.@) 01489 */ 01490 BOOL WINAPI SetupSetFileQueueAlternatePlatformA(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCSTR catalogfile) 01491 { 01492 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_a(catalogfile)); 01493 return FALSE; 01494 } 01495 01496 01497 /*********************************************************************** 01498 * SetupSetFileQueueAlternatePlatformW (SETUPAPI.@) 01499 */ 01500 BOOL WINAPI SetupSetFileQueueAlternatePlatformW(HSPFILEQ handle, PSP_ALTPLATFORM_INFO platform, PCWSTR catalogfile) 01501 { 01502 FIXME("(%p, %p, %s) stub!\n", handle, platform, debugstr_w(catalogfile)); 01503 return FALSE; 01504 } 01505 01506 01507 /*********************************************************************** 01508 * SetupInitDefaultQueueCallback (SETUPAPI.@) 01509 */ 01510 PVOID WINAPI SetupInitDefaultQueueCallback( HWND owner ) 01511 { 01512 return SetupInitDefaultQueueCallbackEx( owner, 0, 0, 0, NULL ); 01513 } 01514 01515 01516 /*********************************************************************** 01517 * SetupInitDefaultQueueCallbackEx (SETUPAPI.@) 01518 */ 01519 PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND owner, HWND progress, UINT msg, 01520 DWORD reserved1, PVOID reserved2 ) 01521 { 01522 struct default_callback_context *context; 01523 01524 if ((context = HeapAlloc( GetProcessHeap(), 0, sizeof(*context) ))) 01525 { 01526 context->owner = owner; 01527 context->progress = progress; 01528 context->message = msg; 01529 } 01530 return context; 01531 } 01532 01533 01534 /*********************************************************************** 01535 * SetupTermDefaultQueueCallback (SETUPAPI.@) 01536 */ 01537 void WINAPI SetupTermDefaultQueueCallback( PVOID context ) 01538 { 01539 HeapFree( GetProcessHeap(), 0, context ); 01540 } 01541 01542 01543 /*********************************************************************** 01544 * SetupDefaultQueueCallbackA (SETUPAPI.@) 01545 */ 01546 UINT WINAPI SetupDefaultQueueCallbackA( PVOID context, UINT notification, 01547 UINT_PTR param1, UINT_PTR param2 ) 01548 { 01549 FILEPATHS_A *paths = (FILEPATHS_A *)param1; 01550 struct default_callback_context *ctx = (struct default_callback_context *)context; 01551 01552 switch(notification) 01553 { 01554 case SPFILENOTIFY_STARTQUEUE: 01555 TRACE( "start queue\n" ); 01556 return TRUE; 01557 case SPFILENOTIFY_ENDQUEUE: 01558 TRACE( "end queue\n" ); 01559 return 0; 01560 case SPFILENOTIFY_STARTSUBQUEUE: 01561 TRACE( "start subqueue %ld count %ld\n", param1, param2 ); 01562 return TRUE; 01563 case SPFILENOTIFY_ENDSUBQUEUE: 01564 TRACE( "end subqueue %ld\n", param1 ); 01565 return 0; 01566 case SPFILENOTIFY_STARTDELETE: 01567 TRACE( "start delete %s\n", debugstr_a(paths->Target) ); 01568 return FILEOP_DOIT; 01569 case SPFILENOTIFY_ENDDELETE: 01570 TRACE( "end delete %s\n", debugstr_a(paths->Target) ); 01571 return 0; 01572 case SPFILENOTIFY_DELETEERROR: 01573 /*Windows Ignores attempts to delete files / folders which do not exist*/ 01574 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND)) 01575 SetupDeleteErrorA(ctx->owner, NULL, paths->Target, paths->Win32Error, 0); 01576 return FILEOP_SKIP; 01577 case SPFILENOTIFY_STARTRENAME: 01578 TRACE( "start rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); 01579 return FILEOP_DOIT; 01580 case SPFILENOTIFY_ENDRENAME: 01581 TRACE( "end rename %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); 01582 return 0; 01583 case SPFILENOTIFY_RENAMEERROR: 01584 SetupRenameErrorA(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0); 01585 return FILEOP_SKIP; 01586 case SPFILENOTIFY_STARTCOPY: 01587 TRACE( "start copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); 01588 return FILEOP_DOIT; 01589 case SPFILENOTIFY_ENDCOPY: 01590 TRACE( "end copy %s -> %s\n", debugstr_a(paths->Source), debugstr_a(paths->Target) ); 01591 return 0; 01592 case SPFILENOTIFY_COPYERROR: 01593 ERR( "copy error %d %s -> %s\n", paths->Win32Error, 01594 debugstr_a(paths->Source), debugstr_a(paths->Target) ); 01595 return FILEOP_SKIP; 01596 case SPFILENOTIFY_NEEDMEDIA: 01597 TRACE( "need media\n" ); 01598 return FILEOP_SKIP; 01599 default: 01600 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 ); 01601 break; 01602 } 01603 return 0; 01604 } 01605 01606 01607 /*********************************************************************** 01608 * SetupDefaultQueueCallbackW (SETUPAPI.@) 01609 */ 01610 UINT WINAPI SetupDefaultQueueCallbackW( PVOID context, UINT notification, 01611 UINT_PTR param1, UINT_PTR param2 ) 01612 { 01613 FILEPATHS_W *paths = (FILEPATHS_W *)param1; 01614 struct default_callback_context *ctx = (struct default_callback_context *)context; 01615 01616 switch(notification) 01617 { 01618 case SPFILENOTIFY_STARTQUEUE: 01619 TRACE( "start queue\n" ); 01620 return TRUE; 01621 case SPFILENOTIFY_ENDQUEUE: 01622 TRACE( "end queue\n" ); 01623 return 0; 01624 case SPFILENOTIFY_STARTSUBQUEUE: 01625 TRACE( "start subqueue %ld count %ld\n", param1, param2 ); 01626 return TRUE; 01627 case SPFILENOTIFY_ENDSUBQUEUE: 01628 TRACE( "end subqueue %ld\n", param1 ); 01629 return 0; 01630 case SPFILENOTIFY_STARTDELETE: 01631 TRACE( "start delete %s\n", debugstr_w(paths->Target) ); 01632 return FILEOP_DOIT; 01633 case SPFILENOTIFY_ENDDELETE: 01634 TRACE( "end delete %s\n", debugstr_w(paths->Target) ); 01635 return 0; 01636 case SPFILENOTIFY_DELETEERROR: 01637 /*Windows Ignores attempts to delete files / folders which do not exist*/ 01638 if ((paths->Win32Error != ERROR_FILE_NOT_FOUND) && (paths->Win32Error != ERROR_PATH_NOT_FOUND)) 01639 SetupDeleteErrorW(ctx->owner, NULL, paths->Target, paths->Win32Error, 0); 01640 return FILEOP_SKIP; 01641 case SPFILENOTIFY_STARTRENAME: 01642 SetupRenameErrorW(ctx->owner, NULL, paths->Source, paths->Target, paths->Win32Error, 0); 01643 return FILEOP_DOIT; 01644 case SPFILENOTIFY_ENDRENAME: 01645 TRACE( "end rename %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); 01646 return 0; 01647 case SPFILENOTIFY_RENAMEERROR: 01648 ERR( "rename error %d %s -> %s\n", paths->Win32Error, 01649 debugstr_w(paths->Source), debugstr_w(paths->Target) ); 01650 return FILEOP_SKIP; 01651 case SPFILENOTIFY_STARTCOPY: 01652 TRACE( "start copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); 01653 return FILEOP_DOIT; 01654 case SPFILENOTIFY_ENDCOPY: 01655 TRACE( "end copy %s -> %s\n", debugstr_w(paths->Source), debugstr_w(paths->Target) ); 01656 return 0; 01657 case SPFILENOTIFY_COPYERROR: 01658 ERR( "copy error %d %s -> %s\n", paths->Win32Error, 01659 debugstr_w(paths->Source), debugstr_w(paths->Target) ); 01660 return FILEOP_SKIP; 01661 case SPFILENOTIFY_NEEDMEDIA: 01662 TRACE( "need media\n" ); 01663 return FILEOP_SKIP; 01664 default: 01665 FIXME( "notification %d params %lx,%lx\n", notification, param1, param2 ); 01666 break; 01667 } 01668 return 0; 01669 } 01670 01671 /*********************************************************************** 01672 * SetupDeleteErrorA (SETUPAPI.@) 01673 */ 01674 01675 UINT WINAPI SetupDeleteErrorA( HWND parent, PCSTR dialogTitle, PCSTR file, 01676 UINT w32error, DWORD style) 01677 { 01678 FIXME( "stub: (Error Number %d when attempting to delete %s)\n", 01679 w32error, debugstr_a(file) ); 01680 return DPROMPT_SKIPFILE; 01681 } 01682 01683 /*********************************************************************** 01684 * SetupDeleteErrorW (SETUPAPI.@) 01685 */ 01686 01687 UINT WINAPI SetupDeleteErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR file, 01688 UINT w32error, DWORD style) 01689 { 01690 FIXME( "stub: (Error Number %d when attempting to delete %s)\n", 01691 w32error, debugstr_w(file) ); 01692 return DPROMPT_SKIPFILE; 01693 } 01694 01695 /*********************************************************************** 01696 * SetupRenameErrorA (SETUPAPI.@) 01697 */ 01698 01699 UINT WINAPI SetupRenameErrorA( HWND parent, PCSTR dialogTitle, PCSTR source, 01700 PCSTR target, UINT w32error, DWORD style) 01701 { 01702 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n", 01703 w32error, debugstr_a(source), debugstr_a(target)); 01704 return DPROMPT_SKIPFILE; 01705 } 01706 01707 /*********************************************************************** 01708 * SetupRenameErrorW (SETUPAPI.@) 01709 */ 01710 01711 UINT WINAPI SetupRenameErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR source, 01712 PCWSTR target, UINT w32error, DWORD style) 01713 { 01714 FIXME( "stub: (Error Number %d when attempting to rename %s to %s)\n", 01715 w32error, debugstr_w(source), debugstr_w(target)); 01716 return DPROMPT_SKIPFILE; 01717 } 01718 01719 01720 /*********************************************************************** 01721 * SetupCopyErrorA (SETUPAPI.@) 01722 */ 01723 01724 UINT WINAPI SetupCopyErrorA( HWND parent, PCSTR dialogTitle, PCSTR diskname, 01725 PCSTR sourcepath, PCSTR sourcefile, PCSTR targetpath, 01726 UINT w32error, DWORD style, PSTR pathbuffer, 01727 DWORD buffersize, PDWORD requiredsize) 01728 { 01729 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n", 01730 w32error, debugstr_a(sourcefile), debugstr_a(sourcepath) ,debugstr_a(targetpath)); 01731 return DPROMPT_SKIPFILE; 01732 } 01733 01734 /*********************************************************************** 01735 * SetupCopyErrorW (SETUPAPI.@) 01736 */ 01737 01738 UINT WINAPI SetupCopyErrorW( HWND parent, PCWSTR dialogTitle, PCWSTR diskname, 01739 PCWSTR sourcepath, PCWSTR sourcefile, PCWSTR targetpath, 01740 UINT w32error, DWORD style, PWSTR pathbuffer, 01741 DWORD buffersize, PDWORD requiredsize) 01742 { 01743 FIXME( "stub: (Error Number %d when attempting to copy file %s from %s to %s)\n", 01744 w32error, debugstr_w(sourcefile), debugstr_w(sourcepath) ,debugstr_w(targetpath)); 01745 return DPROMPT_SKIPFILE; 01746 } 01747 01748 /*********************************************************************** 01749 * pSetupGetQueueFlags (SETUPAPI.@) 01750 */ 01751 DWORD WINAPI pSetupGetQueueFlags( HSPFILEQ handle ) 01752 { 01753 struct file_queue *queue = handle; 01754 return queue->flags; 01755 } 01756 01757 /*********************************************************************** 01758 * pSetupSetQueueFlags (SETUPAPI.@) 01759 */ 01760 BOOL WINAPI pSetupSetQueueFlags( HSPFILEQ handle, DWORD flags ) 01761 { 01762 struct file_queue *queue = handle; 01763 queue->flags = flags; 01764 return TRUE; 01765 } Generated on Fri May 25 2012 04:24:22 for ReactOS by
1.7.6.1
|