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