Raphael wrote:
Changelog: - semi implementation of advpack APIs LaunchINFSection/LaunchINFSectionEx - semi implementation of advpack API ExtractFiles - setupapi: correct and check pExtractFiles return code
I have a few comments:
------------------------------------------------------------------------ @@ -91,30 +105,132 @@ }
/*********************************************************************** - * LaunchINFSection (ADVPACK.@) - */ -void WINAPI LaunchINFSection( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show ) -{ - FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show ); -} - -/*********************************************************************** * LaunchINFSectionEx (ADVPACK.@) */ -void WINAPI LaunchINFSectionEx( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show ) +static UINT LaunchINFSectionEx_CabExtractCallBackA(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2) { - FIXME("(%p %p %s %d): stub\n", hWnd, hInst, debugstr_a(cmdline), show ); -} + LPCSTR file = (LPCSTR) Context; + PFILE_IN_CABINET_INFO_A pInfo = (PFILE_IN_CABINET_INFO_A) Param1; + if ( Notification != SPFILENOTIFY_FILEINCABINET ) return 0; + assert( 0 != Param1 );
Why bother with the assert? You'll crash more nicely by just dereferencing the NULL pointer. At least then you'll get a backtrace in the debugger.
+ if (0 != strcmp(file, pInfo->NameInCabinet)) return FILEOP_SKIP; + lstrcpyA(pInfo->FullTargetName, pInfo->NameInCabinet); + TRACE("Extraction of '%s'\n", pInfo->NameInCabinet); + return FILEOP_DOIT; +} + +HRESULT WINAPI LaunchINFSectionEx( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show ) +{ + CHAR inf_name[512]; + CHAR section_name[512]; + CHAR cab_name[512]; + CHAR szFlags[48]; + CHAR szShow[2]; + DWORD dwFlags; + CHAR* cursor = NULL; + SIZE_T sz = 0; + BOOL bTest; + HINF hinf; + void* callback_context;
-/* this structure very closely resembles parameters of RunSetupCommand() */ -typedef struct -{ - HWND hwnd; - LPCSTR title; - LPCSTR inf_name; - LPCSTR dir; - LPCSTR section_name; -} SETUPCOMMAND_PARAMS; + FIXME("(%p %p %s %d): semi-stub\n", hWnd, hInst, debugstr_a(cmdline), show ); + + cursor = strchr(cmdline, ','); + if (NULL == cursor) { return E_INVALIDARG; }
This is just personal preference, but the extra brackets there aren't needed and don't add to the readability and I haven't seen this style used elsewhere in the Wine source code.
+ sz = (cursor - cmdline) + 1; + lstrcpynA(inf_name, cmdline, sz); inf_name[sz] = 0; + cmdline = cursor + 1; + + cursor = strchr(cmdline, ','); + if (NULL == cursor) { return E_INVALIDARG; } + sz = (cursor - cmdline) + 1; + lstrcpynA(section_name, cmdline, sz); section_name[sz] = 0; + cmdline = cursor + 1; + + cursor = strchr(cmdline, ','); + if (NULL == cursor) { return E_INVALIDARG; } + sz = (cursor - cmdline) + 1; + lstrcpynA(cab_name, cmdline, sz); cab_name[sz] = 0; + cmdline = cursor + 1; + + cursor = strchr(cmdline, ','); + if (NULL == cursor) { return E_INVALIDARG; } + sz = (cursor - cmdline) + 1; + lstrcpynA(szFlags, cmdline, sz); szFlags[sz] = 0; + cmdline = cursor + 1; + + lstrcpynA(szShow, cmdline, 2); szShow[1] = 0; + + dwFlags = atol(szFlags); + + TRACE("cab name('%s')\n", cab_name); + TRACE("inf name('%s')\n", inf_name); + TRACE("inf section name('%s')\n", section_name); + TRACE("flags('%s','%lu')\n", szFlags, dwFlags); + TRACE("nShow('%s')\n", szShow); + + if (dwFlags & 0x04) { + FIXME("dwFlags: Quiet Mode\n"); + } + if (dwFlags & 0x08) { + FIXME("dwFlags: Don't Run GrpConv\n"); + FIXME("Unsupported\n"); return E_NOTIMPL; + } + if (dwFlags & 16) { + FIXME("dwFlags: Force self-updating\n"); + FIXME("Unsupported\n"); return E_NOTIMPL; + } + if (dwFlags & 32) { + FIXME("dwFlags: Backup data before install\n"); + } + if (dwFlags & 64) { + FIXME("dwFlags: Rollback data to previous state\n"); + /*FIXME("Unsupported\n"); return E_NOTIMPL;*/ + } + if (dwFlags & 128) { + FIXME("dwFlags: Validate Backup data before install\n"); + FIXME("Unsupported\n"); return E_NOTIMPL; + } + if (dwFlags & 256) { + FIXME("dwFlags: Rollback data to previous state\n"); + FIXME("Unsupported\n"); return E_NOTIMPL; + } + if (dwFlags & 512) { + FIXME("dwFlags: Force delay of OCX registration\n"); + FIXME("Unsupported\n"); return E_NOTIMPL; + } + + if (0 != strcmp(cab_name, "")) { + FIXME("Unsupported Cab Extraction\n"); return E_NOTIMPL;
Is this left over debugging code?
+ bTest = SetupIterateCabinetA(cab_name, 0, + (PSP_FILE_CALLBACK_A) LaunchINFSectionEx_CabExtractCallBackA, + (LPVOID) inf_name);
Don't cast LaunchINFSectionEx_CabExtractCallBackA. That's a recipe for using a function with an incorrect calling convention and trashing the stack.
+ if (!bTest) return E_FAIL;
Don't use E_FAIL. Try to return a proper error code, preferably using what native returns in this circumstance by adding a test case.
+ } + + hinf = SetupOpenInfFileA(inf_name, NULL, INF_STYLE_WIN4, NULL); + if (hinf == INVALID_HANDLE_VALUE) { + ERR("Failed to SetupOpenInfFileA(%s)\n", inf_name); + return E_FAIL;
Again, don't use E_FAIL. Also consider adding some more debugging information to the error message (like, say, the value returned by GetLastError()).
+ } + + callback_context = SetupInitDefaultQueueCallback(hWnd); + bTest = SetupInstallFromInfSectionA(NULL, hinf, + section_name, + SPINST_ALL, + NULL, NULL, 0, + SetupDefaultQueueCallbackA, + callback_context, + NULL, NULL); + SetupTermDefaultQueueCallback(callback_context); + SetupCloseInfFile(hinf); + + if (!bTest) { + ERR("Failed to SetupInstallFromInfSectionA(%s, %s)\n", inf_name, section_name); + return E_FAIL;
Again, don't use E_FAIL - return a proper error code.
+ } + return S_OK; +}
/*********************************************************************** * DoInfInstall (ADVPACK.@) @@ -144,6 +260,15 @@ }
/*********************************************************************** + * LaunchINFSection (ADVPACK.@) + */ +HRESULT WINAPI LaunchINFSection( HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show ) +{ + FIXME("(%p %p %s %d): semi-stub\n", hWnd, hInst, debugstr_a(cmdline), show );
Can you give us a clue as to what the difference between LaunchINFSection and LaunchINFSectionEx might be by adding a comment? If you don't know, a comment would still be appreciated saying that it should be doing something different here.
+ return LaunchINFSectionEx( hWnd, hInst, cmdline, show ); +} + +/*********************************************************************** * IsNTAdmin (ADVPACK.@) */ BOOL WINAPI IsNTAdmin( DWORD reserved, PDWORD pReserved ) @@ -395,16 +520,59 @@ /*********************************************************************** * ExtractFiles (ADVPACK.@) * + * @param CabName: Cabinet file path + * @param ExpandDir: Extraction Output Directory + * @param Flags: UNKNOWN + * @param FileList: if NULL extract all files + * else UNKNOWN + *
I don't think that is a c2man compatible documentation format.
* BUGS * Unimplemented */ +typedef struct +{ + DWORD Flags; + LPCSTR ExpandDir; + LPCSTR FileList; +} ExtractFiles_CabExtractCallBackA_params_t; + +static UINT ExtractFiles_CabExtractCallBackA(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2) +{ + ExtractFiles_CabExtractCallBackA_params_t* pParams = (ExtractFiles_CabExtractCallBackA_params_t*) Context; + PFILE_IN_CABINET_INFO_A pInfo = (PFILE_IN_CABINET_INFO_A) Param1; + if ( Notification != SPFILENOTIFY_FILEINCABINET ) return 0; + assert( 0 != Param1 ); + assert( 0 != Param2 ); + /** stupid heuristic: waiting for better: ie. understanding what is FileList format */ + if (NULL != pParams->FileList) + { + if (NULL == strstr(pParams->FileList, pInfo->NameInCabinet)) return FILEOP_SKIP; + } + lstrcpyA(pInfo->FullTargetName, pParams->ExpandDir); + /** we should test if pParams->ExpandDir finished with "\" but each app examples i found have it */ + lstrcatA(pInfo->FullTargetName, pInfo->NameInCabinet); + TRACE("Extraction '%s' to '%s' (wanted Path was '%s')\n", pInfo->NameInCabinet, pInfo->FullTargetName, pParams->ExpandDir); + return FILEOP_DOIT; +}
HRESULT WINAPI ExtractFiles ( LPCSTR CabName, LPCSTR ExpandDir, DWORD Flags, LPCSTR FileList, LPVOID LReserved, DWORD Reserved) { - FIXME("(%p %p 0x%08lx %p %p 0x%08lx): stub\n", CabName, ExpandDir, Flags, + ExtractFiles_CabExtractCallBackA_params_t params; + BOOL bTest; + + FIXME("(%p %p 0x%08lx %p %p 0x%08lx): semi-stub\n", CabName, ExpandDir, Flags, FileList, LReserved, Reserved); - return E_FAIL; + + params.Flags = Flags; + params.ExpandDir = ExpandDir; + params.FileList = FileList; + + bTest = SetupIterateCabinetA(CabName, 0, + (PSP_FILE_CALLBACK_A) ExtractFiles_CabExtractCallBackA, + (LPVOID) ¶ms);
Again, don't cast ExtractFiles_CabExtractCallBackA. Just fix up the declaration of that function if it issues a warning here.
+ if (!bTest) return E_FAIL;
Again, don't use E_FAIL. -- Rob Shearman